You are right, you cannot easily use different indexes for different attributes (in your cases and texture coordinates).
A common example is a cube. If you want to display a backlit cube, you need normals. There are only 8 positions on the cube, but each side of the cube needs 3 different normals for the same positions as for each face dividing this position. This means that you only need 24 vertices, 4 for each of the 6 faces of the cube.
If you have a file format that has separate indexes for different attributes, you need to expand them so that each unique combination of attributes (position, normal, texture coordination, etc.) is in your buffers.
Most game engines will do this offline. In other words, they will write some tool that reads the OBJ file, expands the various attributes, and then writes the data back in advance. This is because generating extended data may take a lot of time at runtime for a large model if you are trying to optimize the data and save only unique vertices.
If you donโt need optimal data, just expand it by index. The number of indexes for each attribute type must be the same.
Note: line items are not special. I talk about this because you said that there is no way to use texture coordinate indices in the same way as for an vertex position. WebGL has no concept of "position". It just has attributes that describe how to retrieve data from buffers. What about these attributes (positions, normals, random data, whatever) is up to you. gl.drawElements indexes the entire combination of attributes that you supply. If you pass an index of 7, it will give you element 7 of each attribute.
Note that the above describes how all 3D engines written in WebGL work. However, you can become creative if you want.
Here is a program that stores positions and normals in textures. Then it puts the indexes in buffers. Since textures are random access, they can therefore have different indices for positions and normals.
var canvas = document.getElementById("c"); var gl = canvas.getContext("webgl"); var ext = gl.getExtension("OES_texture_float"); if (!ext) { alert("need OES_texture_float extension cause I'm lazy");
body { margin: 0; } canvas { width: 100vw; height: 100vh; display: block; }
<script src="//twgljs.org/dist/2.x/twgl-full.min.js"></script> <script id="vshader" type="whatever"> attribute float a_positionIndex; attribute float a_normalIndex; attribute vec4 a_pos; uniform sampler2D u_positions; uniform vec2 u_positionsSize; uniform sampler2D u_normals; uniform vec2 u_normalsSize; uniform mat4 u_mvpMatrix; uniform mat4 u_mvMatrix; varying vec3 v_normal; </script> <script id="fshader" type="whatever"> precision mediump float; uniform vec4 u_color; uniform vec3 u_lightDirection; varying vec3 v_normal; void main() { float light = dot( normalize(v_normal), u_lightDirection) * 0.5 + 0.5; gl_FragColor = vec4(u_color.rgb * light, u_color.a); } </script> <canvas id="c"></canvas>
gman Feb 25 '14 at 9:10 2014-02-25 09:10
source share