简体   繁体   English

无法弄清楚如何在twgl中做纹理工作

[英]cannot ever figure out how to do texture jobs in twgl

This is the code I have for vs/fs and a simple cube that I want to put on to my canvas. 这是我为vs / fs编写的代码,以及我想要放在画布上的简单多维数据集。 some of the part is omitted for the sake of lengthiness. 为了冗长,省略了一些部分。

<script id="cube-vs" type="notjs">
    precision highhp float;
    attribute vec3 vpos;
    attribute vec3 vnormal;
    attribute vec2 vtex;
    varying vec3 fColor;
    varying vec3 fNormal;
    varying vec2 fTexCoord;

    uniform mat4 view;
    uniform mat4 proj;
    uniform mat4 model;
    uniform vec3 lightdir;
    uniform vec3 cubecolor;

    void main(void) {
        gl_Position = proj * view * model * vec4(vpos, 1.0);
        vec4 normal = normalize(model * vec4(vnormal,0.0));
        float diffuse = .2 + abs(dot(normal, vec4(lightdir,0.0)));
        fColor = (cubecolor * diffuse);
        fTexCoord = vtex;
    }
</script>
<script id="cube-fs" type="notjs">

    precision highhp float;

    varying vec3 fColor;
    varying vec3 fNormal;
    varying vec2 fTexCoord;

    uniform sampler2D texSampler;

    void main(void) {
        vec4 texColor = texture2d(texSampler, fTexCoord);
        gl_FragColor = vec4(fColor*texColor.xyz,1.0);
    }
</script>

the cube 立方体

...

    Cube.prototype.init = function(drawingState) {
        var gl=drawingState.gl;
        // create the shaders once - for all cubes
        if (!shaderProgram) {
            shaderProgram = twgl.createProgramInfo(gl, ["tree-vs", "tree-fs"]);
        }
        if (!buffers) {
            var arrays = {
                vpos : { numComponents: 3, data: [...] },
                vnormal : {numComponents:3, data: [...]},
                vtex : {numComponents:2, data: [
                    1,0,0,0,0,1,1,1,
                    1,0,0,0,0,1,1,1,
                    1,0,0,0,0,1,1,1,
                    1,0,0,0,0,1,1,1,
                    1,0,0,0,0,1,1,1,
                    1,0,0,0,0,1,1,1,
                ]},
                indices : {[...]}
                };
            buffers = twgl.createBufferInfoFromArrays(gl,arrays);
        }
        if (!texture) {
            texture = twgl.createTexture(gl, {src:textures/tree.jpg});
        }    
    };
    Cube.prototype.draw = function(drawingState) {
        var modelM = twgl.m4.scaling([this.size*1.4,this.size*1.4,this.size*1.4]);
        twgl.m4.setTranslation(modelM,this.position,modelM);
        var gl = drawingState.gl;
        gl.useProgram(shaderProgram.program);
        twgl.setBuffersAndAttributes(gl,shaderProgram,buffers);
        twgl.setUniforms(shaderProgram,{
            view:drawingState.view, proj:drawingState.proj, lightdir:drawingState.sunDirection,
            cubecolor:this.color, model: modelM, texSampler: texture);
        twgl.drawBufferInfo(gl, gl.TRIANGLES, buffers);
    };

the cube worked fine without texture but when I tried to put texture on, it never works I tried almost everything and I still can't figure out how to put texture on. 这个立方体工作得很好而没有纹理,但是当我试图将纹理打开时,它从不起作用我几乎尝试了所有东西,我仍然无法弄清楚如何将纹理放在上面。 so, how can i put texture on? 所以,我怎么能把纹理放在上面?

any hints would be very much appreciated. 任何提示都将非常感激。

*********edit I have managed to successfully upload the texture coordinates and uniforms but the image does not show up and the cube is colored light blue. *********编辑我已成功上传纹理坐标和制服,但图像没有显示,立方体颜色为浅蓝色。 any suggestions would be very much appreciated. 任何建议将非常感谢。

It would be nice if you could provide a working example instead of just parts of the code. 如果您能提供一个工作示例而不仅仅是代码的一部分,那将是很好的。 There's several typos in the code above. 上面的代码中有几个拼写错误。 For example in the setUniforms part there's no closing } . 例如,在setUniforms部分中没有关闭} In the createTexture part there's no quotes on the url. createTexture部分中,url上没有引号。 You spelled highp as highhp and texture2D as texture2d . 你将highp拼写为highhp ,将texture2D拼写为texture2d I assume if you say it's running though without textures those are just transcription errors because if not you should see very clear errors in the JavaScript console. 我假设如果你说没有纹理它正在运行那些只是转录错误,因为如果不是你应该在JavaScript控制台中看到非常明显的错误。

It's not clear what's wrong but when debugging WebGL the first I'd do is check the JavaScript console. 目前尚不清楚是什么问题,但在调试WebGL时,我要做的第一件事就是检查JavaScript控制台。 Are there any messages about un-renderable textures? 是否有关于不可渲染纹理的消息?

No? 没有? Then the next thing i'd do is change the fragment shader to a solid color 接下来我要做的就是将片段着色器更改为纯色

<script id="cube-fs" type="notjs">

    precision highhp float;

    varying vec3 fColor;
    varying vec3 fNormal;
    varying vec2 fTexCoord;

    uniform sampler2D texSampler;

    void main(void) {
        vec4 texColor = texture2d(texSampler, fTexCoord);
        gl_FragColor = vec4(fColor*texColor.xyz,1.0);
gl_FragColor = vec4(1,0,0,1);  // -------ADDED-------------------------
    }
</script>

If you see your cube then yes, the issue is related to the texture. 如果你看到你的立方体然后是,那么问题与纹理有关。 If not the issue is somewhere else. 如果不是,问题就在其他地方。

Let's assume you see a red cube. 我们假设你看到一个红色的立方体。 Ok, next thing is to check the texture coordinates. 好的,接下来要检查纹理坐标。 I'd change the fragment shader to this 我将片段着色器更改为此

<script id="cube-fs" type="notjs">

    precision highhp float;

    varying vec3 fColor;
    varying vec3 fNormal;
    varying vec2 fTexCoord;

    uniform sampler2D texSampler;

    void main(void) {
        vec4 texColor = texture2d(texSampler, fTexCoord);
        gl_FragColor = vec4(fColor*texColor.xyz,1.0);
gl_FragColor = vec4(fTexCoord,0,1);  // -------CHANGED-------------------------
    }
</script>

You should see the cube now with red->green shading. 您现在应该使用红色 - >绿色阴影看到立方体。 If not you've got bad texture coordinates. 如果不是你的纹理坐标不好。

If that looks correct the next thing I might try is put the shader back the way it was originally then check if the variable texture is actually set. 如果看起来正确,我可能尝试的下一件事就是将着色器放回原来的样式,然后检查是否实际设置了变量texture

There's a bunch of ways I could check this. 有很多方法可以检查这个。

  1. Use the WebGL Inspector 使用WebGL检查器

  2. Use the standard JavaScript debugger. 使用标准的JavaScript调试器。 Put a breakpoint on the setUniforms part. setUniforms部分放置一个断点。 Inspect the variables 检查变量

  3. Do something like this 做这样的事情

     var uniforms = { view:drawingState.view, proj:drawingState.proj, lightdir:drawingState.sunDirection, cubecolor:this.color, model: modelM, texSampler: texture, }; window.u = uniforms; twgl.setUniforms(shaderProgram, uniforms); 

    Now open the JavaScript console and type u.texSampler . 现在打开JavaScript控制台并输入u.texSampler It should print something like 它应该打印出类似的东西

     WebGLTexture {} 

    If it doesn't then probably texture is not the variable you think it is 如果没有那么texture可能不是你认为的变量

One other question is are you rendering constantly using requestAnimationFrame as in 另一个问题是你是否经常使用requestAnimationFrame进行渲染

function render() {
  // draw stuff like maybe call someCube.draw(drawingState)
  ...
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

I ask because textures are loaded asynchronously so if you are only rendering once then you won't see any textures because they have not yet been loaded. 我问,因为纹理是异步加载的,所以如果你只渲染一次,那么你将看不到任何纹理,因为它们还没有被加载。

You have a few options. 你有几个选择。

  1. Render constantly (like the example above) 不断渲染(如上例所示)

    twgl will default to a 1x1 pixel texture so rendering should work. twgl将默认为1x1像素纹理,因此渲染应该有效。 Then the image is finally loaded it will update the texture 然后图像最终加载它将更新​​纹理

  2. Wait for the texture to load. 等待纹理加载。

    If you don't want to render until the texture is ready then you can add a callback to twgl.createTexture and it will call you back when the texture is ready. 如果您不希望渲染直到纹理准备就绪,那么您可以向twgl.createTexture添加回调,它会在纹理准备好时回调您。

The other thing to do is to start with a working sample 另一件事是从一个工作样本开始

 var m4 = twgl.m4; // <!------------ ADDED var v3 = twgl.v3; // <!------------ ADDED // not sure why these are globals?!???! var shaderProgram; // <!------------ ADDED var texture; // <!------------ ADDED var buffers; // <!------------ ADDED var canvas = document.querySelector("canvas"); // <!------------ ADDED var drawingState = { // <!------------ ADDED gl: canvas.getContext("webgl"), // <!------------ ADDED view: m4.inverse(m4.lookAt([3,3,6], [0, 0, 0], [0, 1, 0])), // <!------------ ADDED proj: m4.perspective( // <!------------ ADDED Math.PI * 0.3, // <!------------ ADDED canvas.clientWidth / canvas.clientHeight, // <!------------ ADDED 0.1, 10), // <!------------ ADDED sunDirection: v3.normalize([2,3,-2]), // <!------------ ADDED }; // <!------------ ADDED function Cube() { // <!-------------------------------------- ADDED this.size = 1; // <!-------------------------------------- ADDED this.position = [0, 0, 0]; // <!-------------------------------------- ADDED this.color = [1, 1, 1]; // <!-------------------------------------- ADDED } // <!-------------------------------------- ADDED Cube.prototype.init = function(drawingState) { var gl=drawingState.gl; // create the shaders once - for all cubes if (!shaderProgram) { shaderProgram = twgl.createProgramInfo(gl, ["cube-vs", "cube-fs"]); // <!---- CHANGED } if (!buffers) { var arrays = { vpos: { numComponents: 3, data: [1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1], }, vnormal: { numComponents: 3, data: [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1], }, vtex: { numComponents: 2, data: [1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1], }, indices: [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23], }; buffers = twgl.createBufferInfoFromArrays(gl,arrays); } if (!texture) { texture = twgl.createTexture(gl, { src: "https://farm6.staticflickr.com/5795/21506301808_efb27ed699_q_d.jpg", crossOrigin: "", // <!--------- not needed if on same server which "texture/tree.jpg" is }); } }; Cube.prototype.draw = function(drawingState) { var modelM = twgl.m4.scaling([this.size*1.4,this.size*1.4,this.size*1.4]); twgl.m4.setTranslation(modelM,this.position,modelM); var gl = drawingState.gl; gl.useProgram(shaderProgram.program); twgl.setBuffersAndAttributes(gl,shaderProgram,buffers); twgl.setUniforms(shaderProgram,{ view:drawingState.view, proj:drawingState.proj, lightdir:drawingState.sunDirection, cubecolor:this.color, model: modelM, texSampler: texture}); twgl.drawBufferInfo(gl, gl.TRIANGLES, buffers); }; var cube = new Cube(); // <!------------ ADDED cube.init(drawingState); // <!------------ ADDED function render() { // <!------------ ADDED var gl = drawingState.gl // <!------------ ADDED gl.enable(gl.DEPTH_TEST); // <!------------ ADDED cube.draw(drawingState); // <!------------ ADDED requestAnimationFrame(render); // <!------------ ADDED } // <!------------ ADDED requestAnimationFrame(render); // <!------------ ADDED 
 canvas { border: 1px solid black; } 
 <script id="cube-vs" type="notjs"> //precision highp float; <!---------------- CHANGED attribute vec3 vpos; attribute vec3 vnormal; attribute vec2 vtex; varying vec3 fColor; varying vec3 fNormal; varying vec2 fTexCoord; uniform mat4 view; uniform mat4 proj; uniform mat4 model; uniform vec3 lightdir; uniform vec3 cubecolor; void main(void) { gl_Position = proj * view * model * vec4(vpos, 1.0); vec4 normal = normalize(model * vec4(vnormal,0.0)); float diffuse = .2 + abs(dot(normal, vec4(lightdir,0.0))); fColor = (cubecolor * diffuse); fTexCoord = vtex; } </script> <script id="cube-fs" type="notjs"> precision highp float; // <!--------- CHANGED (should probably use mediump though) varying vec3 fColor; varying vec3 fNormal; varying vec2 fTexCoord; uniform sampler2D texSampler; void main(void) { vec4 texColor = texture2D(texSampler, fTexCoord); // < !-------- CHANGED gl_FragColor = vec4(fColor*texColor.xyz,1.0); } </script> <canvas></canvas> <script src="https://twgljs.org/dist/twgl-full.min.js"></script> 

One more question, are you running a webserver? 还有一个问题,你在运行网络服务器吗? WebGL requires a web server to read textures. WebGL需要Web服务器来读取纹理。 Note, running a web server is trival. 请注意,运行Web服务器很简单。 A really good one is here . 一个非常好的是在这里 Just download the version for your OS then 只需下载适用于您的操作系统的版本

path/to/devd-download/devd path/to/project

Then go to http://localhost:8000/nameOfYourHtmlFile.html 然后转到http://localhost:8000/nameOfYourHtmlFile.html

I'm assuming this was not the issue because if it was you'd have seen a clear error in the JavaScript console about not being able to load the texture but you haven't mentioned errors in the JavaScript console 我假设这不是问题,因为如果是这样你在JavaScript控制台中看到一个明显的错误,即无法加载纹理,但你没有在JavaScript控制台中提到错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM