Parcourir la source

Manual texture loading with CORS

Ryan Joseph il y a 7 ans
Parent
commit
a7fd249d38
5 fichiers modifiés avec 68 ajouts et 63 suppressions
  1. 2 1
      Pas2JS_WebGL_OBJ.pas
  2. 24 17
      Pas2JS_WebGL_Terrain.js
  3. 41 40
      Pas2JS_WebGL_Terrain.pas
  4. 1 4
      Terrain.pas
  5. 0 1
      html/Pas2JS_WebGL_Terrain.html

+ 2 - 1
Pas2JS_WebGL_OBJ.pas

@@ -132,10 +132,11 @@ begin
 	gl.Enable(gl.CULL_FACE);
 	gl.CullFace(gl.BACK);
 
+	// set projection transform
 	projTransform := TMat4.Perspective(60.0, canvas.width / canvas.height, 0.1, 2000);
-
 	shader.SetUniformMat4('projTransform', projTransform);
 
+	// set view transform
 	viewTransform := TMat4.Identity;
 	viewTransform := viewTransform.Multiply(TMat4.Translate(0, -3, -20));
 	shader.SetUniformMat4('viewTransform', viewTransform);

+ 24 - 17
Pas2JS_WebGL_Terrain.js

@@ -2120,6 +2120,7 @@ rtl.module("program",["System","Terrain","Noise","Mat4","GLUtils","GLTypes","Sys
   this.terrainResolution = 128;
   this.flySpeed = 1.3;
   this.visiblity = 4;
+  this.textureLoaded = false;
   rtl.createClass($mod,"TTilingTerrain",pas.Terrain.TTerrain,function () {
     this.$init = function () {
       pas.Terrain.TTerrain.$init.call(this);
@@ -2150,6 +2151,7 @@ rtl.module("program",["System","Terrain","Noise","Mat4","GLUtils","GLTypes","Sys
     $mod.viewTransform = pas.Mat4.TMat4.$create("Identity");
     $mod.viewTransform = $mod.viewTransform.Multiply(pas.Mat4.TMat4.$create("Translate",[$mod.camera.x,$mod.camera.y,$mod.camera.z]));
     $mod.shader.SetUniformMat4("viewTransform",$mod.viewTransform);
+    $mod.shader.SetUniformMat4("inverseViewTransform",$mod.viewTransform.Inverse());
     $mod.lightPosition.z += $mod.flySpeed;
     $mod.shader.SetUniformVec3("lightPosition",new pas.GLTypes.TVec3($mod.lightPosition));
     $mod.camera.z -= $mod.flySpeed;
@@ -2176,17 +2178,30 @@ rtl.module("program",["System","Terrain","Noise","Mat4","GLUtils","GLTypes","Sys
     };
   };
   this.AnimateCanvas = function (time) {
-    $mod.DrawCanvas();
+    if ($mod.textureLoaded) $mod.DrawCanvas();
     if ($mod.canvasAnimationHandler !== 0) $mod.canvasAnimationHandler = window.requestAnimationFrame($mod.AnimateCanvas);
   };
   this.StartAnimatingCanvas = function () {
     $mod.canvasAnimationHandler = window.requestAnimationFrame($mod.AnimateCanvas);
   };
+  this.LoadedTexture = function (event) {
+    var Result = false;
+    var texture = null;
+    texture = $mod.gl.createTexture();
+    $mod.gl.bindTexture($mod.gl.TEXTURE_2D,texture);
+    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_WRAP_S,$mod.gl.CLAMP_TO_EDGE);
+    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_WRAP_T,$mod.gl.CLAMP_TO_EDGE);
+    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_MIN_FILTER,$mod.gl.LINEAR);
+    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_MAG_FILTER,$mod.gl.LINEAR);
+    $mod.gl.texImage2D($mod.gl.TEXTURE_2D,0,$mod.gl.RGBA,$mod.gl.RGBA,$mod.gl.UNSIGNED_BYTE,rtl.getObject(event.target));
+    $mod.textureLoaded = true;
+    Result = true;
+    return Result;
+  };
   this.canvas = null;
   this.vertexShaderSource = "";
   this.fragmentShaderSource = "";
-  this.element = null;
-  this.texture = null;
+  this.img = null;
   $mod.$main = function () {
     $mod.debugConsole = document.getElementById("debug-console");
     $mod.canvas = document.createElement("canvas");
@@ -2209,35 +2224,27 @@ rtl.module("program",["System","Terrain","Noise","Mat4","GLUtils","GLTypes","Sys
     $mod.shader.Use();
     $mod.gl.clearColor(0.9,0.9,0.9,1);
     $mod.gl.viewport(0,0,$mod.canvas.width,$mod.canvas.height);
-    $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT);
     $mod.gl.enable($mod.gl.DEPTH_TEST);
     $mod.gl.enable($mod.gl.BLEND);
     $mod.gl.enable($mod.gl.CULL_FACE);
     $mod.gl.cullFace($mod.gl.BACK);
     $mod.projTransform = pas.Mat4.TMat4.$create("Perspective",[60.0,$mod.canvas.width / $mod.canvas.height,0.1,2000]);
     $mod.shader.SetUniformMat4("projTransform",$mod.projTransform);
-    $mod.viewTransform = pas.Mat4.TMat4.$create("Identity");
-    $mod.shader.SetUniformMat4("viewTransform",$mod.viewTransform);
-    $mod.shader.SetUniformMat4("inverseViewTransform",$mod.viewTransform.Inverse());
     $mod.lightPosition = new pas.GLTypes.TVec3(pas.GLTypes.V3(0,$mod.terrainSize / 2,-($mod.terrainSize / 2)));
     $mod.shader.SetUniformVec3("lightPosition",new pas.GLTypes.TVec3($mod.lightPosition));
     $mod.shader.SetUniformVec3("lightColor",new pas.GLTypes.TVec3(pas.GLTypes.V3(1,1,1)));
     $mod.shader.SetUniformFloat("shineDamper",1000);
     $mod.shader.SetUniformFloat("reflectivity",1);
     $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT + $mod.gl.DEPTH_BUFFER_BIT);
-    $mod.modelTransform = pas.Mat4.TMat4.$create("Identity");
-    $mod.shader.SetUniformMat4("modelTransform",$mod.modelTransform);
     $mod.camera.x = -($mod.terrainSize / 2);
     $mod.camera.y = -($mod.terrainSize / 4);
     $mod.camera.z = -($mod.terrainSize / 2);
-    $mod.element = document.getElementById("terrain-texture");
-    $mod.texture = $mod.gl.createTexture();
-    $mod.gl.bindTexture($mod.gl.TEXTURE_2D,$mod.texture);
-    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_WRAP_S,$mod.gl.CLAMP_TO_EDGE);
-    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_WRAP_T,$mod.gl.CLAMP_TO_EDGE);
-    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_MIN_FILTER,$mod.gl.LINEAR);
-    $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_MAG_FILTER,$mod.gl.LINEAR);
-    $mod.gl.texImage2D($mod.gl.TEXTURE_2D,0,$mod.gl.RGBA,$mod.gl.RGBA,$mod.gl.UNSIGNED_BYTE,rtl.getObject($mod.element));
+    $mod.img = document.createElement("IMG");
+    $mod.img.setAttribute("height","512");
+    $mod.img.setAttribute("width","512");
+    $mod.img.setAttribute("crossOrigin","anonymous");
+    $mod.img.setAttribute("src","res\/ground.jpg");
+    $mod.img.onload = $mod.LoadedTexture;
     $mod.terrainNoise = pas.Noise.TNoise.$create("Create$2",[pas.Noise.RandomNoiseSeed(1).slice(0)]);
     $mod.maps = new Array();
     $mod.StartAnimatingCanvas();

+ 41 - 40
Pas2JS_WebGL_Terrain.pas

@@ -24,6 +24,7 @@ var
 	terrainResolution: integer = 128;
 	flySpeed: single = 1.3;
 	visiblity: integer = 4;
+	textureLoaded: boolean = false;
 
 type
 	TTilingTerrain = class (TTerrain)
@@ -58,6 +59,7 @@ begin
 	viewTransform := TMat4.Identity;
 	viewTransform := viewTransform.Multiply(TMat4.Translate(camera.x, camera.y, camera.z));
 	shader.SetUniformMat4('viewTransform', viewTransform);
+	shader.SetUniformMat4('inverseViewTransform', viewTransform.Inverse);
 
 	// move light with camera
 	lightPosition.z += flySpeed;
@@ -74,8 +76,6 @@ begin
 	if startIndex < 0 then
 		startIndex := 0;
 
-	// https://gamedev.stackexchange.com/questions/23625/how-do-you-generate-tileable-perlin-noise
-
 	//debugConsole.innerHTML := IntToStr(startIndex)+'/'+IntToStr(endIndex) + VecStr(terrainCoord);
 
 	for i := startIndex to endIndex do
@@ -87,10 +87,6 @@ begin
 						map.neighbor := TTilingTerrain(maps[i - 1]);
 					map.Generate;
 
-					// TODO: take the edge and set the heights to same size as the neighbor
-					// we need to do this pre-vertex generation so we need a callback
-					// or interface (which doesn't exist yet)
-
 					maps.push(map);
 
 					// NOTE: does this free memory in JS?
@@ -104,18 +100,12 @@ begin
 			shader.SetUniformMat4('modelTransform', modelTransform);
 			map.Draw;
 		end;
-
-	//if abs(terrainCoord.z) > 10 then
-	//	begin
-	//		writeln('cancel animation');
-	//		window.cancelAnimationFrame(canvasAnimationHandler);
-	//		canvasAnimationHandler := 0;
-	//	end;
 end;
 
 procedure AnimateCanvas(time: TDOMHighResTimeStamp);
 begin
-	DrawCanvas;
+	if textureLoaded then
+		DrawCanvas;
 
 	if canvasAnimationHandler <> 0 then
 		canvasAnimationHandler := window.requestAnimationFrame(@AnimateCanvas);
@@ -126,6 +116,22 @@ begin
 	canvasAnimationHandler := window.requestAnimationFrame(@AnimateCanvas);
 end;
 
+function LoadedTexture (event: TEventListenerEvent): boolean;
+var
+	texture: TJSWebGLTexture;
+begin
+	texture := gl.createTexture;
+	gl.bindTexture(gl.TEXTURE_2D, texture);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+	gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, TJSTexImageSource(event.target));
+
+	textureLoaded := true;
+	result := true;
+end;
+
 var
   canvas: TJSHTMLCanvasElement;
   i: integer;
@@ -135,6 +141,7 @@ var
   fragmentShaderSource: string;
   buffer: TJSWebGLBuffer;
   element: TJSElement;
+  img: TJSHTMLElement;
   texture: TJSWebGLTexture;
 begin
 
@@ -171,27 +178,16 @@ begin
 	// prepare context
 	gl.clearColor(0.9, 0.9, 0.9, 1);
 	gl.viewport(0, 0, canvas.width, canvas.height);
-	gl.clear(gl.COLOR_BUFFER_BIT);
 
-	// NOTE: we don't need this in WebGL
-	//gl.enable(gl.TEXTURE_2D);
 	gl.enable(gl.DEPTH_TEST);
 	gl.enable(gl.BLEND);
 	gl.Enable(gl.CULL_FACE);
 	gl.CullFace(gl.BACK);
 
+	// set projection transform
 	projTransform := TMat4.Perspective(60.0, canvas.width / canvas.height, 0.1, 2000);
-
 	shader.SetUniformMat4('projTransform', projTransform);
 
-	viewTransform := TMat4.Identity;
-	//viewTransform := viewTransform.Multiply(TMat4.Translate(-10, -3, -20));
-	shader.SetUniformMat4('viewTransform', viewTransform);
-
-	// NOTE: webgl glsl doesn't have the inverse function
-	// so we need to do this here
-	shader.SetUniformMat4('inverseViewTransform', viewTransform.Inverse);
-
 	// lighting
 	lightPosition := V3(0, terrainSize / 2, -(terrainSize/2));
 	shader.SetUniformVec3('lightPosition', lightPosition);
@@ -203,27 +199,32 @@ begin
 
 	gl.clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT);
 
-	modelTransform := TMat4.Identity;
-	shader.SetUniformMat4('modelTransform', modelTransform);
-
 	camera.x := -(terrainSize/2);
 	camera.y := -(terrainSize/4);
 	camera.z := -(terrainSize/2);
 
 	// load terrain texture from image tag
-	element := document.getElementById('terrain-texture');
-
-	texture := gl.createTexture;
-	gl.bindTexture(gl.TEXTURE_2D, texture);
-	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
-	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
-	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
-	gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, TJSTexImageSource(element));
-
+	//img := TJSHTMLElement(document.getElementById('terrain-texture'));
+	//    <image id="terrain-texture" crossOrigin="anonymous" src="res/ground.jpg" hidden/>
+	img := TJSHTMLElement(document.createElement('IMG'));
+	img.setAttribute('height', '512');
+	img.setAttribute('width', '512');
+	img.setAttribute('crossOrigin', 'anonymous');
+	img.setAttribute('src', 'res/ground.jpg');
+	img.onload := @LoadedTexture;
+
+	//texture := gl.createTexture;
+	//gl.bindTexture(gl.TEXTURE_2D, texture);
+	//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+	//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+	//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+	//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+	//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, TJSTexImageSource(img));
+	//textureLoaded := true;
+
+	// TODO: RandSeed doesn't seem to work so we get a random seed each time
 	terrainNoise := TNoise.Create(RandomNoiseSeed(1));
 	maps := TJSArray.new;
 
-	//map.Draw;
 	StartAnimatingCanvas;
 end.

+ 1 - 4
Terrain.pas

@@ -61,8 +61,6 @@ function TTerrain.GetHeightForVertex (localX, localY, x, y: integer): TNoiseFloa
 begin
 	result := noise.GetNoise(x, y, heights.GetWidth, heights.GetHeight, 4, 3);
 	result := Power(result, 5);
-	// terraces
-	//result := Round(result * 24) / 24;
 	result := (result * 20) - 6;	
 end;
 
@@ -94,7 +92,7 @@ begin
 		noise := TNoise.Create(RandomNoiseSeed(1));
 	heights := TMatrix.Create(terrainResolution, terrainResolution);
 
-	verticies := TJSArray.new;//TMemoryBuffer.Create(heights.GetWidth * heights.GetHeight * kModelVertexFloats * 4);
+	verticies := TJSArray.new;
 	indicies := TJSArray.new;
 
 	for y := 0 to heights.GetWidth - 1 do
@@ -114,7 +112,6 @@ begin
 			
 			ModelVertexAddToArray(vertex, verticies);
 		end;
-	//writeln('terrain floats: ', verticies.length);
 
 	for gz := 0 to heights.GetWidth - 2 do
 	for gx := 0 to heights.GetHeight - 2 do

+ 0 - 1
html/Pas2JS_WebGL_Terrain.html

@@ -5,7 +5,6 @@
   </head>
   <body>
     <pre id="debug-console"></pre>
-    <image id="terrain-texture" src="res/ground.jpg" hidden/>
 
   	<script type="application/glsl" id="vertex.glsl">
       attribute vec3 in_position;