OpenGL Display Wavefront OBJ using shader...

Started by
1 comment, last by wzcoder 6 years, 11 months ago

Hi,

I'm a newbie on OpenGL shader... every one need to start from beginning...

What is already do :

I write a small C++ sample to display 3d object with vertex color, i display a small cube using the code and shaders (put at the end of this message).

I also found how draw a face (2 triangles with 3 textures mix - code and shade rat the end).

My question is about a more complex use of shader :

I write and .obj parser i have theses data :

- an array of vertex (x,y,z)

- an array of 2d mapping (u,v)

- an array of face : 3 duo (each one contain : index of vertex, index of mapping)

- and maybe a texture index.

My target is to reduce data store by OpenGL : some vertex have the same x,y,z but may have a different u,v and\or texture.

Instead of duplicate duo [x,y,z], [u,v], an want to use an array of vertices [x,y,z], an array of mapping [u,v] and send face info [index of vertex, index of mapping] to shader and rebuild [x,y,z], [u,v] fril theses infos..

I suppose i need to map with c++ theses datas on vertex shader :
attribute vec4 vtxVertices; // [x,y,z]
attribute vec2 vtxMapping; // [u,v]
attribute vec2 vtxFace; // [vertex index, mapping index]

My supposition :

Vertex shader is call for each vertex, but i don't understand how call if for each face index to retrieve associate vertex index and mapping index... to rebuild [x,y,z], [u,v]

If some one could help me to understand how vertex\fragment shader work it will be great ;)

Thanks for your help,

Wcdr

= Vertex color =========================================================================================

= Drawing code C++11\14 STL =================================


// Get id for shader attributes.
GLint iVertexPosition { itPosition->second };
GLint iVertexColor { itColor->second };

// Set vertex position.
glEnableVertexAttribArray ( iVertexPosition );
glVertexAttribPointer ( iVertexPosition, 3, GL_FLOAT, GL_FALSE, sizeof ( CVertexDescB ), &( m_vertex[0].m_oPosition ));

// Set vertex color.
glEnableVertexAttribArray ( iVertexColor );
glVertexAttribPointer ( iVertexColor, 4, GL_FLOAT, GL_FALSE, sizeof ( CVertexDescB ), &( m_vertex[0].m_oColor ));

// Draw cube.
glDrawElements ( GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, m_indice );

// Restore client state.
glDisableVertexAttribArray ( iVertexColor );
glDisableVertexAttribArray ( iVertexPosition );

= Fragment Shader ========================================


#version 100
precision highp float;
varying vec4 varColor;

void main()
{
    // Set color.
    gl_FragColor = varColor;
}

= Vertex Shader ===========================================


#version 100
precision highp float;

uniform mat4 matrixProjection;
uniform mat4 matrixView;
uniform mat4 matrixModel;

attribute vec4 vtxPosition;
attribute vec4 vtxColor;

varying vec4 varColor;

void main ()
{        
    // Set color.
    varColor = vtxColor;

    // Set position of the current vertex.
    gl_Position = matrixProjection * matrixView * matrixModel * vtxPosition;
}

= Texture mapping =======================================================================================

= Drawing code C++11\14 STL =================================


// Get attributes index.
GLint iVertexPosition { itPosition->second };
GLint iTextureCoord { itTextureCoord->second };

// Set texture mapping.
glEnableVertexAttribArray ( iTextureCoord );
glVertexAttribPointer ( iTextureCoord, 2, GL_FLOAT, GL_FALSE, sizeof ( CVertexDescA ), &( m_vertex[0].m_oUV ));

// Set vertex.
glEnableVertexAttribArray ( iVertexPosition );
glVertexAttribPointer ( iVertexPosition, 3, GL_FLOAT, GL_FALSE, sizeof ( CVertexDescA ), &( m_vertex[0].m_oPosition ));

// Draw mesh for video support.
glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, m_indice );

// Restore client state.
glDisableVertexAttribArray ( iVertexPosition );
glDisableVertexAttribArray ( iTextureCoord );

= Fragment Shader ========================================


uniform mat4 matrixProjection;
uniform mat4 matrixView;
uniform mat4 matrixModel;

attribute vec4 vtxPosition;
attribute vec2 uvPlan;

varying vec2 varTexCoord;

void main ()
{            
    // Get textures coordinate.
    varTexCoord = uvPlan;
        
    // Set position of the current vertex.
    gl_Position = matrixProjection * matrixView * matrixModel * vtxPosition;
}

= Vertex Shader ===========================================


// Texture handler.
uniform sampler2D texPlane0;    // Y.
uniform sampler2D texPlane1;    // U.
uniform sampler2D texPlane2;    // V.

varying vec2 varTexCoord;

void main()
{
    // Pre-calculate YUV.
    float fY = 1.164 * ( texture2D ( texPlane0, varTexCoord ).r - 0.0625 );
    float fU =           texture2D ( texPlane1, varTexCoord ).r - 0.5;
    float fV =           texture2D ( texPlane2, varTexCoord ).r - 0.5;

    // Calc final RGB color from YUV.
    vec4 rgbColor;
    rgbColor.x = fY              + 1.793 * fV;
    rgbColor.y = fY - 0.213 * fU + 0.533 * fV;
    rgbColor.z = fY + 2.112 * fU;

    // Set color.
    gl_FragColor = rgbColor;
}
Advertisement

Indexing always indexes at the same index position on each vertex attributes (vertices, normals, colors, texture coordinates...), except if you use instancing (but that won't help you for this). So index 2 will retrieve the second vertex of the vertex attribute array, the second texture coordinates of the texture coordinates array, and so on.

So you have to repeat your attributes each time another one changes: if two vertices are the same, but their texture coordinates change, then repeat the vertices.

You'll find later that, most of the time, when this happens, normals will also not be the same (especially for cubes).

Vertex shaders have absolutely no knowledge about other vertices. Just like fragment shaders have no knowledge about other fragments.

Hi,

Thanks for this fast answer, your explanation is very clear (i found a small graph that confirm your answer see attach file).

I will simplify rendering by grouping face by material and remove duplicated duo common to all material group, maybe i will caching result to speedup loading... or convert obj to a custom binary format.

Best regards,

wcdr

-- This thread could be closed --

This topic is closed to new replies.

Advertisement