2014-10-16 3 views
0

약간의 손실이 있습니다. 다른 정점에 다른 텍스처를 설정하려고합니다. WebGL은이 작업을 매우 불필요하게 어렵게 만듭니다. 기본적으로 원하는 꼭지점의 행렬이있는 텍스트 파일이 있습니다. (예 : http://jdmdev.net/Foundation/index.html)여러 텍스처를 제공하는 여러 셰이더 프로그램

하지만 지금은 다른 질감을 설정하기 위해 'texture atlassing'이라는 무언가를해야합니다. 온라인으로 구현하는 방법에 관한 문서는 절대적으로 없습니다.

나는 WebGL에 매우 익숙하지만 광범위한 프로그래밍 배경을 가지고있어서 나에게 주어진 어떤 개념을 이해할 수있다. 만약 내가 뭔가를보고 있거나 적어도 약간의 문서를 볼 수 있다면.

그래서 질감 아트지가 그림에서 빠져 있다고 생각합니다. 그러나, 나는 WebGL 파이프 라인을 understadning하는 경우뿐만 아니라 나는 생각합니다. 셰이더/버텍스 프로그램을 여러 개 만들 수 없습니까? 그렇다면 어떻게 할 수 있습니까? 나는 직접적인 예제가 필요하지 않지만, 단지 몇몇 코드는 놀라운 일을 할 것이다. 나는 이것을 한 번보아야 만하고 얻을 것이다. 그러나 이것은 매우 새롭기 때문에 웹상에서 유용한 물건을 찾는 것은 불가능하다. 주어진 도움을 주셔서 감사합니다.

코드는이 질문에 대답에 도움이되지만 여기에 내가 기본적으로 그래서 learningwebgltutorials.com

<script id="shader-fs" type="x-shader/x-fragment"> 
    precision mediump float; 

    varying vec2 vTextureCoord; 

    uniform sampler2D uSampler; 
    uniform sampler2D uSampler2; 

    void main(void) { 
     gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); 
    } 
</script> 

<script id="shader-vs" type="x-shader/x-vertex"> 
    attribute vec3 aVertexPosition; 
    attribute vec2 aTextureCoord; 

    uniform mat4 uMVMatrix; 
    uniform mat4 uPMatrix; 

    varying vec2 vTextureCoord; 

    void main(void) { 
     gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); 
     vTextureCoord = aTextureCoord; 
    } 
</script> 

<script id="shader2-fs" type="x-shader/x-fragment"> 
    precision mediump float; 

    varying vec2 vTextureCoord; 

    uniform sampler2D uSampler; 
    uniform sampler2D uSampler2; 

    void main(void) { 
     gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); 
    } 
</script> 

<script id="shader2-vs" type="x-shader/x-vertex"> 
    attribute vec3 aVertexPosition; 
    attribute vec2 aTextureCoord; 

    uniform mat4 uMVMatrix; 
    uniform mat4 uPMatrix; 

    varying vec2 vTextureCoord; 

    void main(void) { 
     gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); 
     vTextureCoord = aTextureCoord; 
    } 
</script> 

<script type="text/javascript"> 

    var gl; 

    function initGL(canvas) { 
     try { 
      gl = canvas.getContext("experimental-webgl"); 
      gl.viewportWidth = canvas.width; 
      gl.viewportHeight = canvas.height; 
     } catch (e) { 
     } 
     if (!gl) { 
      alert("Could not initialise WebGL, sorry :-("); 
     } 
    } 


    function getShader(gl, id) { 
     var shaderScript = document.getElementById(id); 
     if (!shaderScript) { 
      return null; 
     } 

     var str = ""; 
     var k = shaderScript.firstChild; 
     while (k) { 
      if (k.nodeType == 3) { 
       str += k.textContent; 
      } 
      k = k.nextSibling; 
     } 

     var shader; 
     if (shaderScript.type == "x-shader/x-fragment") { 
      shader = gl.createShader(gl.FRAGMENT_SHADER); 
     } else if (shaderScript.type == "x-shader/x-vertex") { 
      shader = gl.createShader(gl.VERTEX_SHADER); 
     } else { 
      return null; 
     } 

     gl.shaderSource(shader, str); 
     gl.compileShader(shader); 

     if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 
      alert(gl.getShaderInfoLog(shader)); 
      return null; 
     } 

     return shader; 
    } 


    var shaderProgram; 

    function initShaders() { 
     var fragmentShader = getShader(gl, "shader-fs"); 
     var vertexShader = getShader(gl, "shader-vs"); 

     shaderProgram = gl.createProgram(); 
     gl.attachShader(shaderProgram, vertexShader); 
     gl.attachShader(shaderProgram, fragmentShader); 
     gl.linkProgram(shaderProgram); 

     if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { 
      alert("Could not initialise shaders"); 
     } 

     gl.useProgram(shaderProgram); 

     shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); 
     gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); 

     shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); 
     gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); 

     shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix"); 
     shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); 
     shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); 
    } 


    function handleLoadedTexture(texture) { 
     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 
     gl.bindTexture(gl.TEXTURE_2D, texture); 
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); 
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 

     gl.bindTexture(gl.TEXTURE_2D, null); 
    } 


    var mudTexture; 
    var rockTexture; 

    function initTexture() { 
     mudTexture = gl.createTexture(); 
     mudTexture.image = new Image(); 
     mudTexture.image.onload = function() { 
      handleLoadedTexture(mudTexture) 
     } 

     mudTexture.image.src = "mud.gif"; 

     rockTexture = gl.createTexture(); 
     rockTexture.image = new Image(); 
     rockTexture.image.onload = function() { 
      handleLoadedTexture(rockTexture) 
     } 

     rockTexture.image.src = "rockstar.gif"; 
    } 


    var mvMatrix = mat4.create(); 
    var mvMatrixStack = []; 
    var pMatrix = mat4.create(); 

    function mvPushMatrix() { 
     var copy = mat4.create(); 
     mat4.set(mvMatrix, copy); 
     mvMatrixStack.push(copy); 
    } 

    function mvPopMatrix() { 
     if (mvMatrixStack.length == 0) { 
      throw "Invalid popMatrix!"; 
     } 
     mvMatrix = mvMatrixStack.pop(); 
    } 


    function setMatrixUniforms() { 
     gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix); 
     gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix); 
    } 


    function degToRad(degrees) { 
     return degrees * Math.PI/180; 
    } 



    var currentlyPressedKeys = {}; 

    function handleKeyDown(event) { 
     currentlyPressedKeys[event.keyCode] = true; 
    } 


    function handleKeyUp(event) { 
     currentlyPressedKeys[event.keyCode] = false; 
    } 


    var pitch = 0; 
    var pitchRate = 0; 

    var yaw = 0; 
    var yawRate = 0; 

    var xPos = 10; 
    var yPos = 0.4; 
    var zPos = 10; 

    var speed = 0; 

    function handleKeys() { 
     if (currentlyPressedKeys[33]) { 
      // Page Up 
      pitchRate = 0.1; 
     } else if (currentlyPressedKeys[34]) { 
      // Page Down 
      pitchRate = -0.1; 
     } else { 
      pitchRate = 0; 
     } 

     if (currentlyPressedKeys[37] || currentlyPressedKeys[65]) { 
      // Left cursor key or A 
      yawRate = 0.1; 
     } else if (currentlyPressedKeys[39] || currentlyPressedKeys[68]) { 
      // Right cursor key or D 
      yawRate = -0.1; 
     } else { 
      yawRate = 0; 
     } 

     if (currentlyPressedKeys[38] || currentlyPressedKeys[87]) { 
      // Up cursor key or W 
      speed = 0.01; 
     } else if (currentlyPressedKeys[40] || currentlyPressedKeys[83]) { 
      // Down cursor key 
      speed = -0.01; 
     } else { 
      speed = 0; 
     } 

    } 


    var worldVertexPositionBuffer = null; 
    var worldVertexTextureCoordBuffer = null; 

    function handleLoadedWorld(data) { 
     var lines = data.split("\n"); 
     var vertexCount = 0; 
     var vertexPositions = []; 
     var vertexTextureCoords = []; 
     for (var i in lines) { 
      var vals = lines[i].replace(/^\s+/, "").split(/\s+/); 
      if (vals.length == 6 && vals[0] != "//") { 
       // It is a line describing a vertex; get X, Y and Z first 
       vertexPositions.push(parseFloat(vals[0])); 
       vertexPositions.push(parseFloat(vals[1])); 
       vertexPositions.push(parseFloat(vals[2])); 
       //document.write(vertexPositions[0]); 
       // And then the texture coords 
       vertexTextureCoords.push(parseFloat(vals[3])); 
       vertexTextureCoords.push(parseFloat(vals[4])); 
       //document.write(vals[4]) + "<br/>"); 
       vertexCount += 1; 
      } 
     } 

     worldVertexPositionBuffer = gl.createBuffer(); 
     gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexPositionBuffer); 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositions), gl.STATIC_DRAW); 
     worldVertexPositionBuffer.itemSize = 3; 
     worldVertexPositionBuffer.numItems = vertexCount; 

     worldVertexTextureCoordBuffer = gl.createBuffer(); 
     gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexTextureCoordBuffer); 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexTextureCoords), gl.STATIC_DRAW); 
     worldVertexTextureCoordBuffer.itemSize = 2; 
     worldVertexTextureCoordBuffer.numItems = vertexCount; 

     document.getElementById("loadingtext").textContent = ""; 
    } 


    function loadWorld() { 
     var request = new XMLHttpRequest(); 
     request.open("GET", "world.txt"); 
     request.onreadystatechange = function() { 
      if (request.readyState == 4) { 
       handleLoadedWorld(request.responseText); 
      } 
     } 
     request.send(); 
    } 

    function loadTextureValues() { 
     var request = new XMLHttpRequest(); 
     request.open("GET", "world.txt"); 
     request.onreadystatechange = function() { 
      if (request.readyState == 4) { 
       getCorrectTexture(request.responseText); 
      } 
     } 
     request.send(); 
    } 

    var matchWithTexture = {}; 

    function getCorrectTexture(data) 
    { 
     var lines = data.split("\n"); 
     var vertexCount = 0; 
     var vertexTextureValueCoords = []; 

     for (var i in lines) { 
      var vals = lines[i].replace(/^\s+/, "").split(/\s+/); 
      if (vals.length == 6 && vals[0] != "//") 
      { 
       //document.write(vertexTextureValueCoords.push(parseFloat(vals[1])) + "</br>"); 
       vertexTextureValueCoords.push(parseFloat(vals[5])); 
       matchWithTexture[vertexCount] = vertexTextureValueCoords[vertexCount]; 
       vertexCount++; 
      } 
     } 
    } 



    function drawScene() { 
     gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 

     if (worldVertexTextureCoordBuffer == null || worldVertexPositionBuffer == null) { 
      return; 
     } 

     mat4.perspective(45, gl.viewportWidth/gl.viewportHeight, 0.1, 100.0, pMatrix); 

     mat4.identity(mvMatrix); 

     mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]); 
     mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]); 
     mat4.translate(mvMatrix, [-xPos, -yPos, -zPos]); 

     gl.activeTexture(gl.TEXTURE0); 
     gl.bindTexture(gl.TEXTURE_2D, mudTexture); 
     gl.activeTexture(gl.TEXTURE1); 
     gl.bindTexture(gl.TEXTURE_2D, rockTexture); 

     loadTextureValues(); 
     for(var key in matchWithTexture) 
     { 
      //document.write(matchWithTexture[key] + "<br/>"); 
      if(matchWithTexture[key] == 1) 
      { 
       gl.uniform1i(shaderProgram.samplerUniform, 0); 
      } 
      else { 
       gl.uniform1i(shaderProgram.samplerUniform, 1); 
      } 
     } 



     gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexTextureCoordBuffer); 
     gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, worldVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0); 

     gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexPositionBuffer); 
     gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, worldVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 

     setMatrixUniforms(); 
     gl.drawArrays(gl.TRIANGLES, 0, worldVertexPositionBuffer.numItems); 
    } 


    var lastTime = 0; 
    // Used to make us "jog" up and down as we move forward. 
    var joggingAngle = 0; 

    function animate() { 
     var timeNow = new Date().getTime(); 
     if (lastTime != 0) { 
      var elapsed = timeNow - lastTime; 

      if (speed != 0) { 
       xPos -= Math.sin(degToRad(yaw)) * speed * elapsed; 
       zPos -= Math.cos(degToRad(yaw)) * speed * elapsed; 

       joggingAngle += elapsed * 0.6; // 0.6 "fiddle factor" - makes it feel more realistic :-) 
       yPos = Math.sin(degToRad(joggingAngle))/20 + 0.4 
      } 

      yaw += yawRate * elapsed; 
      pitch += pitchRate * elapsed; 

     } 
     lastTime = timeNow; 
    } 


    function tick() { 
     requestAnimFrame(tick); 
     handleKeys(); 
     drawScene(); 
     animate(); 
    } 



    function webGLStart() { 
     var canvas = document.getElementById("lesson10-canvas"); 
     initGL(canvas); 
     initShaders(); 
     initTexture(); 
     loadWorld(); 

     gl.clearColor(0.0, 0.0, 0.0, 1.0); 
     gl.enable(gl.DEPTH_TEST); 

     document.onkeydown = handleKeyDown; 
     document.onkeyup = handleKeyUp; 

     tick(); 
    } 

</script> 

에서 사용 내 코드의 얼마나 확실하지 내가 제 2의 쉐이더/정점 프로그램을 작성하고 있었다 않은 모든 여전히 작동합니다. 그렇다면 첫 번째 쉐이더/버텍스 프로그램과는 다른 정보로 어떻게 구현할 수 있습니까?

그리고 마지막 질문은 다음과 같습니다. webgl의 모든 것을 시도하는 대신 라이브러리를 사용하는 것이 더 가치가 있습니까? 내 말은, webgl에서 수행 한 모든 Google 검색을 통해 대부분의 예제/자습서는 모두 three.js 또는 babylon.js..etc를 사용하여 완료됩니다. 내가하고있는 일을하려고 할 가치가 있는지 궁금해. 나는 질문이 무엇이겠습니까, 전문적인 설정은 내가 webgl을 똑바로 해 주길 바랄 것입니까, 아니면 (가장 가능성이 높은) 라이브러리를 사용하고 싶습니까? 나는 webgl을 프로그래밍하는 계획조차하지 않고 단지 인터뷰에서 나올지 안다. 이미 정점과 텍스처 좌표에 대한 텍스트 파일에서 정보를 파싱 된 이후, 수있는 방법이 있어야한다

https://github.com/jordmax12/WebGL/blob/master/Foundation%205/foundation_2.js

NO 텍스처 별명 VIA

솔루션은 (텍스처 자체에 대해이 작업을 수행하는 텍스처 앨리어싱없이).

+0

[6면으로 큐브를 텍스처링하는 방법을 설명하는이 페이지의 아래쪽에 텍스처 아트 레이싱의 간단한 예가 있습니다.] (http://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html). 텍스처 좌표를 사용하여 어느 정점에 대한 텍스처 맵의 부분을 선택합니다. 따라서 모든 삼각형은 텍스처의 다른 부분을 선택할 수 있습니다. 두 인접한 삼각형이 서로 다른 질감을 사용하면 삼각형이 꼭지점을 공유하지 않는다는 것을 의미합니다. 정점은 위치 좌표와 텍스처 좌표로 구성되며 텍스 좌표는 서로 다르기 때문에 꼭지를 공유 할 수 없기 때문입니다. – gman

+0

@gman 멋지다! 실제로 나는 간단한 텍스트 파일을 파싱하는 방법을 알아 냈고, 텍스처링을 atlasing하지 않고도 바인딩하도록했습니다. 누구든지이 작업을 원한다면 내 질문에 링크를 게시 할 것입니다. 나는 그것이 훨씬 더 쉽고, 더 '프로그래밍 적'이라고 느낀다. –

답변

0

하나씩 다른 꼭지점에 다른 텍스처와 쉐이더를 사용할 수 있습니다. 문제는 이것이 비효율적이라는 것입니다. 좋은 성능을 위해, 나는 atlasing 주위에 방법이 있다고 생각하지 않습니다. 그래서 모두가 이것을하고 있습니다.

나는 atlasing을 단순화하기 위해 어떤 three.js 유틸리티도 알지 못합니다. (그러나 나는 three.js에 익숙하지 않습니다.)

텍스처를 커다란 캔버스에 그리는 유틸리티를 구현하고 런타임에 atlas를 생성하고 좌표를 추적하는 일은 간단합니다. 설정 후 도구는 기본적으로 좌표와 텍스처 이름 또는 ID를 순수 좌표 배열 (텍스처 좌표 포함)로 변환합니다.

라이브러리를 사용해야하는지 여부는 실제로 수행하려는 계획에 따라 다릅니다. 보관 모드 API가 유스 케이스에서 작동하면 three.js를 사용하는 것이 좋습니다.

+0

당신은 당신 자신의 예제를 가지고 있습니까? ai 길 찾기와 cpu 포커를 알고리즘으로 베팅하면서 머리를 감쌀 수는 있지만 문자 그대로 아무것도 설명하지 않고 내가 설명하는 것을 수행하는 방법을 보여 주지만 설명하는 것은 정확히 내가하려는 것입니다. –

관련 문제