void Geometry_UpdateVertexPositions( SGeometry *geometry, uint firstVertex, uint vertexCount, const void *data ) { uint index; GLuint vertexArrayObject; GLuint vertexBuffer; uint offset; uint size; Prof_Start( PROF_GEOMETRY_UPDATE ); OVR::GL_CheckErrors( "before Geometry_UpdateVertexPositions" ); index = geometry->updateIndex % BUFFER_COUNT; vertexArrayObject = geometry->vertexArrayObjects[index]; assert( vertexArrayObject ); glBindVertexArrayOES_( vertexArrayObject ); vertexBuffer = geometry->vertexBuffers[index]; assert( vertexBuffer ); glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer ); offset = firstVertex * sizeof( float ) * 3; size = vertexCount * sizeof( float ) * 3; glBufferSubData( GL_ARRAY_BUFFER, offset, size, data ); glBindVertexArrayOES_( 0 ); OVR::GL_CheckErrors( "after Geometry_UpdateVertexPositions" ); Prof_Stop( PROF_GEOMETRY_UPDATE ); }
// Debug tool to draw outlines of a 3D bounds void AppLocal::DrawBounds( const Vector3f &mins, const Vector3f &maxs, const Matrix4f &mvp, const Vector3f &color ) { Matrix4f scaled = mvp * Matrix4f::Translation( mins ) * Matrix4f::Scaling( maxs - mins ); const GlProgram & prog = untexturedMvpProgram; glUseProgram(prog.program); glLineWidth( 1.0f ); glUniform4f(prog.uColor, color.x, color.y, color.z, 1); glUniformMatrix4fv(prog.uMvp, 1, GL_FALSE /* not transposed */, scaled.Transposed().M[0] ); glBindVertexArrayOES_( unitCubeLines.vertexArrayObject ); glDrawElements(GL_LINES, unitCubeLines.indexCount, GL_UNSIGNED_SHORT, NULL); glBindVertexArrayOES_( 0 ); }
//============================== // OvrDebugLinesLocal::InitVBO void OvrDebugLinesLocal::InitVBO( GlGeometry & geo, LineVertex_t * vertices, const int maxVerts, LineIndex_t * indices, const int maxIndices ) { const int numVertexBytes = maxVerts * sizeof( LineVertex_t ); // create vertex array object glGenVertexArraysOES_( 1, &geo.vertexArrayObject ); glBindVertexArrayOES_( geo.vertexArrayObject ); // create the vertex buffer glGenBuffers( 1, &geo.vertexBuffer ); glBindBuffer( GL_ARRAY_BUFFER, geo.vertexBuffer ); glBufferData( GL_ARRAY_BUFFER, numVertexBytes, (void*)vertices, GL_DYNAMIC_DRAW ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_POSITION ); // x, y and z glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_POSITION, 3, GL_FLOAT, false, sizeof( LineVertex_t ), (void*)0 ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_COLOR ); // color glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_COLOR, 4, GL_FLOAT, true, sizeof( LineVertex_t ), (void*)12 ); const int numIndexBytes = maxIndices * sizeof( LineIndex_t ); glGenBuffers( 1, &geo.indexBuffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, geo.indexBuffer ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, numIndexBytes, (void*)indices, GL_STATIC_DRAW ); geo.indexCount = 0; // nothing to render right now }
void WarpGeometry_CreateQuad( WarpGeometry * geometry ) { struct vertices_t { float positions[4][3]; float uvs[4][2]; float colors[4][4]; } vertices = { { { -1, -1, 0 }, { -1, 1, 0 }, { 1, -1, 0 }, { 1, 1, 0 } }, { { 0, 1 }, { 1, 1 }, { 0, 0 }, { 1, 0 } }, { { 1, 1, 1, 0 }, { 1, 1, 1, 0 }, { 1, 1, 1, 0 }, { 1, 1, 1, 0 } } }; unsigned short indices[6] = { 0, 1, 2, 2, 1, 3 }; geometry->vertexCount = 4; geometry->indexCount = 6; glGenVertexArraysOES_( 1, &geometry->vertexArrayObject ); glBindVertexArrayOES_( geometry->vertexArrayObject ); glGenBuffers( 1, &geometry->vertexBuffer ); glBindBuffer( GL_ARRAY_BUFFER, geometry->vertexBuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), &vertices, GL_STATIC_DRAW ); glGenBuffers( 1, &geometry->indexBuffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, geometry->indexBuffer ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_POSITION ); glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_POSITION, 3, GL_FLOAT, false, sizeof( vertices.positions[0] ), (const GLvoid *)offsetof( vertices_t, positions ) ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_UV0 ); glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_UV0, 2, GL_FLOAT, false, sizeof( vertices.uvs[0] ), (const GLvoid *)offsetof( vertices_t, uvs ) ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_COLOR ); glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_COLOR, 4, GL_FLOAT, false, sizeof( vertices.colors[0] ), (const GLvoid *)offsetof( vertices_t, colors ) ); glBindVertexArrayOES_( 0 ); }
//============================== // BitmapFontSurfaceLocal::Render3D // render the font surface by transforming each vertex block and copying it into the VBO // TODO: once we add support for multiple fonts per surface, this should not take a BitmapFont for input. void BitmapFontSurfaceLocal::Render3D( BitmapFont const & font, Matrix4f const & worldMVP ) const { GL_CheckErrors( "BitmapFontSurfaceLocal::Render3D - pre" ); //SPAM( "BitmapFontSurfaceLocal::Render3D" ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glDepthMask( GL_FALSE ); glDisable( GL_CULL_FACE ); // Draw the text glyphs glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, AsLocal( font ).GetTexture() ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glUseProgram( AsLocal( font ).GetFontProgram().program ); glUniformMatrix4fv( AsLocal( font ).GetFontProgram().uMvp, 1, GL_FALSE, worldMVP.M[0] ); float textColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; glUniform4fv( AsLocal( font ).GetFontProgram().uColor, 1, textColor ); // draw all font vertices glBindVertexArrayOES_( Geo.vertexArrayObject ); glDrawElements( GL_TRIANGLES, Geo.indexCount, GL_UNSIGNED_SHORT, NULL ); glBindVertexArrayOES_( 0 ); glEnable( GL_CULL_FACE ); glDisable( GL_BLEND ); glDepthMask( GL_FALSE ); GL_CheckErrors( "BitmapFontSurfaceLocal::Render3D - post" ); }
void GlGeometry::Create( const VertexAttribs & attribs, const Array< TriangleIndex > & indices ) { vertexCount = attribs.position.GetSizeI(); indexCount = indices.GetSizeI(); glGenBuffers( 1, &vertexBuffer ); glGenBuffers( 1, &indexBuffer ); glGenVertexArraysOES_( 1, &vertexArrayObject ); glBindVertexArrayOES_( vertexArrayObject ); glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer ); Array< uint8_t > packed; PackVertexAttribute( packed, attribs.position, VERTEX_ATTRIBUTE_LOCATION_POSITION, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.normal, VERTEX_ATTRIBUTE_LOCATION_NORMAL, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.tangent, VERTEX_ATTRIBUTE_LOCATION_TANGENT, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.binormal, VERTEX_ATTRIBUTE_LOCATION_BINORMAL, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.color, VERTEX_ATTRIBUTE_LOCATION_COLOR, GL_FLOAT, 4 ); PackVertexAttribute( packed, attribs.uv0, VERTEX_ATTRIBUTE_LOCATION_UV0, GL_FLOAT, 2 ); PackVertexAttribute( packed, attribs.uv1, VERTEX_ATTRIBUTE_LOCATION_UV1, GL_FLOAT, 2 ); PackVertexAttribute( packed, attribs.jointIndices, VERTEX_ATTRIBUTE_LOCATION_JOINT_INDICES, GL_INT, 4 ); PackVertexAttribute( packed, attribs.jointWeights, VERTEX_ATTRIBUTE_LOCATION_JOINT_WEIGHTS, GL_FLOAT, 4 ); glBufferData( GL_ARRAY_BUFFER, packed.GetSize() * sizeof( packed[0] ), packed.GetDataPtr(), GL_STATIC_DRAW ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.GetSizeI() * sizeof( indices[0] ), indices.GetDataPtr(), GL_STATIC_DRAW ); glBindVertexArrayOES_( 0 ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_POSITION ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_NORMAL ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_TANGENT ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_BINORMAL ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_COLOR ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_UV0 ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_UV1 ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_JOINT_INDICES ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_JOINT_WEIGHTS ); }
// Draw a screen to an eye buffer the same way it would be drawn as a // time warp overlay. void AppLocal::DrawScreenDirect( const GLuint texid, const ovrMatrix4f & mvp ) { const Matrix4f mvpMatrix( mvp ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, texid ); glUseProgram( OverlayScreenDirectProgram.program ); glUniformMatrix4fv( OverlayScreenDirectProgram.uMvp, 1, GL_FALSE, mvpMatrix.Transposed().M[0] ); glBindVertexArrayOES_( unitSquare.vertexArrayObject ); glDrawElements( GL_TRIANGLES, unitSquare.indexCount, GL_UNSIGNED_SHORT, NULL ); glBindTexture( GL_TEXTURE_2D, 0 ); // don't leave it bound }
// Draw a screen to an eye buffer the same way it would be drawn as a // time warp overlay. void DrawScreenDirect( const GLuint texid, const ovrMatrix4f & mvp ) { const OVR::Matrix4f mvpMatrix( mvp ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, texid ); static OVR::GlProgram prog; if ( !prog.program ) { prog = OVR::BuildProgram( "uniform mat4 Mvpm;\n" "attribute vec4 Position;\n" "attribute vec2 TexCoord;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_Position = Mvpm * Position;\n" " oTexCoord = TexCoord;\n" "}\n" , "uniform sampler2D Texture0;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_FragColor = texture2D( Texture0, oTexCoord );\n" "}\n" ); } glUseProgram( prog.program ); glUniformMatrix4fv( prog.uMvp, 1, GL_FALSE, mvpMatrix.Transposed().M[0] ); static OVR::GlGeometry unitSquare; if ( unitSquare.vertexArrayObject == 0 ) { unitSquare = OVR::BuildTesselatedQuad( 1, 1 ); } glBindVertexArrayOES_( unitSquare.vertexArrayObject ); glDrawElements( GL_TRIANGLES, unitSquare.indexCount, GL_UNSIGNED_SHORT, NULL ); glBindTexture( GL_TEXTURE_2D, 0 ); // don't leave it bound }
void GlGeometry::Update( const VertexAttribs & attribs ) { vertexCount = attribs.position.GetSizeI(); glBindVertexArrayOES_( vertexArrayObject ); glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer ); Array< uint8_t > packed; PackVertexAttribute( packed, attribs.position, VERTEX_ATTRIBUTE_LOCATION_POSITION, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.normal, VERTEX_ATTRIBUTE_LOCATION_NORMAL, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.tangent, VERTEX_ATTRIBUTE_LOCATION_TANGENT, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.binormal, VERTEX_ATTRIBUTE_LOCATION_BINORMAL, GL_FLOAT, 3 ); PackVertexAttribute( packed, attribs.color, VERTEX_ATTRIBUTE_LOCATION_COLOR, GL_FLOAT, 4 ); PackVertexAttribute( packed, attribs.uv0, VERTEX_ATTRIBUTE_LOCATION_UV0, GL_FLOAT, 2 ); PackVertexAttribute( packed, attribs.uv1, VERTEX_ATTRIBUTE_LOCATION_UV1, GL_FLOAT, 2 ); PackVertexAttribute( packed, attribs.jointIndices, VERTEX_ATTRIBUTE_LOCATION_JOINT_INDICES, GL_INT, 4 ); PackVertexAttribute( packed, attribs.jointWeights, VERTEX_ATTRIBUTE_LOCATION_JOINT_WEIGHTS, GL_FLOAT, 4 ); glBufferData( GL_ARRAY_BUFFER, packed.GetSize() * sizeof( packed[0] ), packed.GetDataPtr(), GL_STATIC_DRAW ); }
//============================== // OvrDebugLinesLocal::Init void OvrDebugLinesLocal::Init() { if ( Initialized ) { // JDC: multi-activity test DROID_ASSERT( !Initialized, "DebugLines" ); return; } // this is only freed by the OS when the program exits if ( LineProgram.vertexShader == 0 || LineProgram.fragmentShader == 0 ) { LineProgram = BuildProgram( DebugLineVertexSrc, DebugLineFragmentSrc ); } const int MAX_VERTS = MAX_DEBUG_LINES * 2; Vertices = new LineVertex_t[ MAX_VERTS ]; // the indices will never change once we've set them up, we just won't necessarily // use all of the index buffer to render. const int MAX_INDICES = MAX_DEBUG_LINES * 2; LineIndex_t * indices = new LineIndex_t[ MAX_INDICES ]; for ( int i = 0; i < MAX_INDICES; ++i ) { indices[i] = i; } InitVBO( DepthGeo, Vertices, MAX_VERTS, indices, MAX_INDICES ); InitVBO( NonDepthGeo, Vertices, MAX_VERTS, indices, MAX_INDICES ); glBindVertexArrayOES_( 0 ); delete [] indices; // never needs to change so we don't keep it around Initialized = true; }
//============================== // OvrDebugLinesLocal::Render void OvrDebugLinesLocal::Render( Matrix4f const & mvp, GlGeometry & geo, OVR::ArrayPOD< DebugLine_t > const & lines, const bool depthTest ) const { if ( lines.GetSizeI() == 0 ) { return; } //LOG( "Rendering %i debug lines", lines.GetSizeI() ); // go through the debug lines and put them in the vertex list int numLines = lines.GetSizeI() < MAX_DEBUG_LINES ? lines.GetSizeI() : MAX_DEBUG_LINES; for ( int i = 0; i < numLines; ++i ) { DebugLine_t const & line = lines[i]; LineVertex_t & v1 = Vertices[i * 2 + 0]; LineVertex_t & v2 = Vertices[i * 2 + 1]; v1.x = line.Start.x; v1.y = line.Start.y; v1.z = line.Start.z; v1.r = line.StartColor.x; v1.g = line.StartColor.y; v1.b = line.StartColor.z; v1.a = line.StartColor.w; v2.x = line.End.x; v2.y = line.End.y; v2.z = line.End.z; v2.r = line.EndColor.x; v2.g = line.EndColor.y; v2.b = line.EndColor.z; v2.a = line.EndColor.w; } glBindVertexArrayOES_( geo.vertexArrayObject ); int numVertices = numLines * 2; int numVertexBytes = numVertices * sizeof( LineVertex_t ); glBindBuffer( GL_ARRAY_BUFFER, geo.vertexBuffer ); glBufferSubData( GL_ARRAY_BUFFER, 0, numVertexBytes, (void*)Vertices ); glBindVertexArrayOES_( geo.vertexArrayObject ); geo.indexCount = numLines * 2; if ( depthTest ) { glEnable( GL_DEPTH_TEST ); glDepthMask( GL_TRUE ); } else { glDisable( GL_DEPTH_TEST ); glDepthMask( GL_FALSE ); } glEnable( GL_BLEND ); glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); glLineWidth( 2.0f ); // aliasing is really bad at 1.0 glUseProgram( LineProgram.program ); glUniformMatrix4fv( LineProgram.uMvp, 1, GL_FALSE, mvp.M[0] ); glDrawElements( GL_LINES, geo.indexCount, GL_UNSIGNED_SHORT, NULL ); glBindVertexArrayOES_( 0 ); glEnable( GL_DEPTH_TEST ); glDepthMask( GL_TRUE ); glDisable( GL_BLEND ); }
//============================== // BitmapFontSurfaceLocal::Finish // transform all vertex blocks into the vertices array so they're ready to be uploaded to the VBO // We don't have to do this for each eye because the billboarded surfaces are sorted / aligned // based on their distance from / direction to the camera view position and not the camera direction. void BitmapFontSurfaceLocal::Finish( Matrix4f const & viewMatrix ) { DROID_ASSERT( this != NULL, "BitmapFont" ); //SPAM( "BitmapFontSurfaceLocal::Finish" ); Matrix4f invViewMatrix = viewMatrix.Inverted(); // if the view is never scaled or sheared we could use Transposed() here instead Vector3f viewPos = invViewMatrix.GetTranslation(); // sort vertex blocks indices based on distance to pivot int const MAX_VERTEX_BLOCKS = 256; vbSort_t vbSort[MAX_VERTEX_BLOCKS]; int const n = VertexBlocks.GetSizeI(); for ( int i = 0; i < n; ++i ) { vbSort[i].VertexBlockIndex = i; VertexBlockType & vb = VertexBlocks[i]; vbSort[i].DistanceSquared = ( vb.Pivot - viewPos ).LengthSq(); } qsort( vbSort, n, sizeof( vbSort[0] ), VertexBlockSortFn ); // transform the vertex blocks into the vertices array CurIndex = 0; CurVertex = 0; // TODO: // To add multiple-font-per-surface support, we need to add a 3rd component to s and t, // then get the font for each vertex block, and set the texture index on each vertex in // the third texture coordinate. for ( int i = 0; i < VertexBlocks.GetSizeI(); ++i ) { VertexBlockType & vb = VertexBlocks[vbSort[i].VertexBlockIndex]; Matrix4f transform; if ( vb.Billboard ) { if ( vb.TrackRoll ) { transform = invViewMatrix; } else { Vector3f textNormal = viewPos - vb.Pivot; textNormal.Normalize(); transform = Matrix4f::CreateFromBasisVectors( textNormal, Vector3f( 0.0f, 1.0f, 0.0f ) ); } transform.SetTranslation( vb.Pivot ); } else { transform.SetIdentity(); transform.SetTranslation( vb.Pivot ); } for ( int j = 0; j < vb.NumVerts; j++ ) { fontVertex_t const & v = vb.Verts[j]; Vertices[CurVertex].xyz = transform.Transform( v.xyz ); Vertices[CurVertex].s = v.s; Vertices[CurVertex].t = v.t; *(UInt32*)(&Vertices[CurVertex].rgba[0]) = *(UInt32*)(&v.rgba[0]); *(UInt32*)(&Vertices[CurVertex].fontParms[0]) = *(UInt32*)(&v.fontParms[0]); CurVertex++; } CurIndex += ( vb.NumVerts / 2 ) * 3; // free this vertex block vb.Free(); } // remove all elements from the vertex block (but don't free the memory since it's likely to be // needed on the next frame. VertexBlocks.Clear(); glBindVertexArrayOES_( Geo.vertexArrayObject ); glBindBuffer( GL_ARRAY_BUFFER, Geo.vertexBuffer ); glBufferSubData( GL_ARRAY_BUFFER, 0, CurVertex * sizeof( fontVertex_t ), (void *)Vertices ); glBindVertexArrayOES_( 0 ); Geo.indexCount = CurIndex; }
//============================== // BitmapFontSurfaceLocal::Init // Initializes the surface VBO void BitmapFontSurfaceLocal::Init( const int maxVertices ) { assert( Geo.vertexBuffer == 0 && Geo.indexBuffer == 0 && Geo.vertexArrayObject == 0 ); assert( Vertices == NULL ); if ( Vertices != NULL ) { delete [] Vertices; Vertices = NULL; } assert( maxVertices % 4 == 0 ); MaxVertices = maxVertices; MaxIndices = ( maxVertices / 4 ) * 6; Vertices = new fontVertex_t[ maxVertices ]; const int vertexByteCount = maxVertices * sizeof( fontVertex_t ); // font VAO glGenVertexArraysOES_( 1, &Geo.vertexArrayObject ); glBindVertexArrayOES_( Geo.vertexArrayObject ); // vertex buffer glGenBuffers( 1, &Geo.vertexBuffer ); glBindBuffer( GL_ARRAY_BUFFER, Geo.vertexBuffer ); glBufferData( GL_ARRAY_BUFFER, vertexByteCount, (void*)Vertices, GL_DYNAMIC_DRAW ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_POSITION ); // x, y and z glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof( fontVertex_t ), (void*)0 ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_UV0 ); // s and t glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_UV0, 2, GL_FLOAT, GL_FALSE, sizeof( fontVertex_t ), (void*)offsetof( fontVertex_t, s ) ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_COLOR ); // color glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( fontVertex_t ), (void*)offsetof( fontVertex_t, rgba ) ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_UV1 ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_LOCATION_FONT_PARMS ); // outline parms glVertexAttribPointer( VERTEX_ATTRIBUTE_LOCATION_FONT_PARMS, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( fontVertex_t ), (void*)offsetof( fontVertex_t, fontParms ) ); fontIndex_t * indices = new fontIndex_t[ MaxIndices ]; const int indexByteCount = MaxIndices * sizeof( fontIndex_t ); // indices never change int numQuads = MaxIndices / 6; int v = 0; for ( int i = 0; i < numQuads; i++ ) { indices[i * 6 + 0] = v + 2; indices[i * 6 + 1] = v + 1; indices[i * 6 + 2] = v + 0; indices[i * 6 + 3] = v + 3; indices[i * 6 + 4] = v + 2; indices[i * 6 + 5] = v + 0; v += 4; } glGenBuffers( 1, &Geo.indexBuffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, Geo.indexBuffer ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, indexByteCount, (void*)indices, GL_STATIC_DRAW ); Geo.indexCount = 0; // if there's anything to render this will be modified glBindVertexArrayOES_( 0 ); delete [] indices; CurVertex = 0; CurIndex = 0; LOG( "BitmapFontSurfaceLocal::Init: success" ); }
void GlGeometry::Draw() const { glBindVertexArrayOES_( vertexArrayObject ); glDrawElements( GL_TRIANGLES, indexCount, ( sizeof( TriangleIndex ) == 2 ) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, NULL ); }
void Geometry_MakeVertexArrayObject( SGeometry *geometry ) { uint index; GLuint vertexArrayObject; GLuint vertexBuffer; GLuint indexBuffer; uint vertexCount; uint positionSize; uint texCoordSize; uint positionOffset; uint texCoordOffset; uint colorOffset; index = geometry->updateIndex % BUFFER_COUNT; vertexBuffer = geometry->vertexBuffers[index]; indexBuffer = geometry->indexBuffers[index]; assert( vertexBuffer ); assert( indexBuffer ); OVR::GL_CheckErrors( "before Geometry_MakeVertexArrayObject" ); vertexArrayObject = geometry->vertexArrayObjects[index]; if ( !vertexArrayObject ) glGenVertexArraysOES_( 1, &vertexArrayObject ); glBindVertexArrayOES_( vertexArrayObject ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer ); glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_POSITION ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_TEXCOORD ); glEnableVertexAttribArray( VERTEX_ATTRIBUTE_COLOR ); vertexCount = geometry->vertexCount; positionSize = sizeof( float ) * 3 * vertexCount; texCoordSize = sizeof( float ) * 2 * vertexCount; positionOffset = 0; texCoordOffset = positionOffset + positionSize; colorOffset = texCoordOffset + texCoordSize; glVertexAttribPointer( VERTEX_ATTRIBUTE_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 3, (void *)( positionOffset ) ); glVertexAttribPointer( VERTEX_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 2, (void *)( texCoordOffset ) ); glVertexAttribPointer( VERTEX_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof( byte ) * 4, (void *)( colorOffset ) ); glBindVertexArrayOES_( 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_POSITION ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_TEXCOORD ); glDisableVertexAttribArray( VERTEX_ATTRIBUTE_COLOR ); geometry->vertexArrayObjects[index] = vertexArrayObject; OVR::GL_CheckErrors( "after Geometry_MakeVertexArrayObject" ); }
// Called by TimeWarp before adding the KHR sync object. void ImageServer::EnterWarpSwap( int eyeTexture ) { ImageServerRequest request = Request.GetState(); if ( request.Sequence <= SequenceCaptured ) { return; } SequenceCaptured = request.Sequence; // create GL objects if necessary if ( !ResampleProg.program ) { WarpProgram_Create( &ResampleProg, "uniform highp mat4 Mvpm;\n" "attribute vec4 Position;\n" "attribute vec2 TexCoord;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_Position = Position;\n" " oTexCoord = vec2( TexCoord.x, 1.0 - TexCoord.y );\n" // need to flip Y "}\n" , "uniform sampler2D Texture0;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_FragColor = texture2D( Texture0, oTexCoord );\n" "}\n" ); } if ( !Quad.vertexArrayObject ) { WarpGeometry_CreateQuad( &Quad ); } // If resolution has changed, delete and reallocate the buffers // These might still be in use, do we trust the driver or try to // deal with it ourselves? if ( request.Resolution != CurrentResolution ) { CurrentResolution = request.Resolution; FreeBuffers(); } // Allocate any resources we need if ( !ResampleRenderBuffer ) { LOG( "Alloc %i res renderbuffer", CurrentResolution ); glGenRenderbuffers( 1, &ResampleRenderBuffer ); glBindRenderbuffer( GL_RENDERBUFFER, ResampleRenderBuffer ); glRenderbufferStorage( GL_RENDERBUFFER, GL_RGB565, CurrentResolution, CurrentResolution ); } if ( !FrameBufferObject ) { LOG( "Alloc FrameBufferObject" ); glGenFramebuffers( 1, &FrameBufferObject ); glBindFramebuffer( GL_FRAMEBUFFER, FrameBufferObject ); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ResampleRenderBuffer ); const GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER ); if (status != GL_FRAMEBUFFER_COMPLETE ) { LOG( "FBO is not complete: 0x%x", status ); } } if ( !PixelBufferObject ) { LOG( "Alloc PixelBufferObject" ); glGenBuffers( 1, &PixelBufferObject ); glBindBuffer( GL_PIXEL_PACK_BUFFER, PixelBufferObject ); glBufferData( GL_PIXEL_PACK_BUFFER, CurrentResolution*CurrentResolution*2, NULL, GL_DYNAMIC_READ ); glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); } // Render the FBO glBindFramebuffer( GL_FRAMEBUFFER, FrameBufferObject ); glDisable( GL_DEPTH_TEST ); glDisable( GL_SCISSOR_TEST ); GL_InvalidateFramebuffer( INV_FBO, true, false ); glViewport( 0, 0, CurrentResolution, CurrentResolution ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, eyeTexture ); glUseProgram( ResampleProg.program ); glBindVertexArrayOES_( Quad.vertexArrayObject ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL ); glBindVertexArrayOES_( 0 ); glUseProgram( 0 ); // unmap the previous PBO mapping if ( PboMappedAddress ) { glBindBuffer( GL_PIXEL_PACK_BUFFER, PixelBufferObject ); glUnmapBuffer_( GL_PIXEL_PACK_BUFFER ); glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); PboMappedAddress = NULL; } // Issue an async read into our PBO #if 1 glBindBuffer( GL_PIXEL_PACK_BUFFER, PixelBufferObject ); glReadPixels( 0, 0, CurrentResolution, CurrentResolution, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0 ); // back to normal memory read operations glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); #else GL_CheckErrors( "before read" ); static short pixels[256*256]; glReadPixels( 0, 0, CurrentResolution, CurrentResolution, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (GLvoid *)pixels ); ImageServerResponse response; response.Data = (void *)pixels; response.Resolution = CurrentResolution; response.Sequence = request.Sequence; Response.SetState( response ); #endif glBindFramebuffer( GL_FRAMEBUFFER, 0 ); GL_CheckErrors( "after read" ); CountdownToSend = 2; }
// Renders a list of pointers to models in order. DrawCounters RenderSurfaceList( const DrawSurfaceList & drawSurfaceList ) { // This state could be made to persist across multiple calls to RenderModelList, // but the benefit would be small. GpuState currentGpuState; GLuint currentTextures[ MAX_PROGRAM_TEXTURES ] = {}; // TODO: This should be a range checked container. const DrawMatrices * currentMatrices = NULL; GLuint currentProgramObject = 0; // default joints if no joints are specified static const Matrix4f defaultJoints[MAX_JOINTS]; // counters DrawCounters counters; // Loop through all the surfaces for ( int surfaceNum = 0; surfaceNum < drawSurfaceList.numDrawSurfaces; surfaceNum++ ) { const DrawSurface & drawSurface = drawSurfaceList.drawSurfaces[ surfaceNum ]; const SurfaceDef & surfaceDef = *drawSurface.surface; const MaterialDef & materialDef = surfaceDef.materialDef; // Update GPU state -- blending, etc if ( !currentGpuState.Equals( materialDef.gpuState ) ) { ChangeGpuState( currentGpuState, materialDef.gpuState ); currentGpuState = materialDef.gpuState; } // Update texture bindings assert( materialDef.numTextures <= MAX_PROGRAM_TEXTURES ); for ( int textureNum = 0; textureNum < materialDef.numTextures; textureNum++ ) { const GLuint texNObj = ( drawSurface.textureOverload == 0 ) ? materialDef.textures[textureNum].texture : drawSurface.textureOverload; if ( currentTextures[textureNum] != texNObj ) { counters.numTextureBinds++; currentTextures[textureNum] = texNObj; glActiveTexture( GL_TEXTURE0 + textureNum ); // Something is leaving target set to 0; assume GL_TEXTURE_2D glBindTexture( materialDef.textures[textureNum].target ? materialDef.textures[textureNum].target : GL_TEXTURE_2D, texNObj ); } } // Update program object assert( materialDef.programObject != 0 ); if ( materialDef.programObject != currentProgramObject ) { counters.numProgramBinds++; currentProgramObject = materialDef.programObject; glUseProgram( currentProgramObject ); // It is possible the program still has the correct MVP, // but we don't want to track it, so reset it anyway. currentMatrices = NULL; } // Update the program parameters if ( drawSurface.matrices != currentMatrices ) { counters.numParameterUpdates++; currentMatrices = drawSurface.matrices; // set the mvp matrix glUniformMatrix4fv( materialDef.uniformMvp, 1, 0, ¤tMatrices->Mvp.M[0][0] ); // set the model matrix if ( materialDef.uniformModel != -1 ) { glUniformMatrix4fv( materialDef.uniformModel, 1, 0, ¤tMatrices->Model.M[0][0] ); } // set the view matrix if ( materialDef.uniformView != -1 ) { glUniformMatrix4fv( materialDef.uniformView, 1, 0, &drawSurfaceList.viewMatrix.M[0][0] ); } // set the projection matrix if ( materialDef.uniformProjection != -1 ) { glUniformMatrix4fv( materialDef.uniformProjection, 1, 0, &drawSurfaceList.projectionMatrix.M[0][0] ); } // set the joint matrices if ( materialDef.uniformJoints != -1 ) { if ( drawSurface.joints != NULL && drawSurface.joints->GetSize() > 0 ) { glUniformMatrix4fv( materialDef.uniformJoints, Alg::Min( drawSurface.joints->GetSizeI(), MAX_JOINTS ), 0, &drawSurface.joints->At( 0 ).M[0][0] ); } else { glUniformMatrix4fv( materialDef.uniformJoints, MAX_JOINTS, 0, &defaultJoints[0].M[0][0] ); } } } for ( int unif = 0; unif < MAX_PROGRAM_UNIFORMS; unif++ ) { const int slot = materialDef.uniformSlots[unif]; if ( slot == -1 ) { break; } counters.numParameterUpdates++; glUniform4fv( slot, 1, materialDef.uniformValues[unif] ); } counters.numDrawCalls++; // Bind all the vertex and element arrays surfaceDef.geo.Draw(); } // set the gpu state back to the default ChangeGpuState( currentGpuState, GpuState() ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, 0 ); glUseProgram( 0 ); glBindVertexArrayOES_( 0 ); return counters; }
void Entity_DrawEntity( SEntity *entity, const OVR::Matrix4f &view ) { STexture *texture; SGeometry *geometry; uint geometryIndex; uint textureIndex; GLuint texId; float uScale; float vScale; GLuint vertexArrayObject; int triCount; int indexOffset; int batchTriCount; int triCountLeft; Prof_Start( PROF_DRAW_ENTITY ); assert( entity ); OVR::GL_CheckErrors( "before Entity_DrawEntity" ); geometry = Registry_GetGeometry( entity->geometryRef ); assert( geometry ); geometryIndex = geometry->drawIndex % BUFFER_COUNT; vertexArrayObject = geometry->vertexArrayObjects[geometryIndex]; if ( !vertexArrayObject ) { Prof_Stop( PROF_DRAW_ENTITY ); return; } glUseProgram( s_ent.shader.program ); glUniformMatrix4fv( s_ent.shader.uMvp, 1, GL_FALSE, view.Transposed().M[0] ); glBindVertexArrayOES_( vertexArrayObject ); glActiveTexture( GL_TEXTURE0 ); if ( entity->textureRef != S_NULL_REF ) { texture = Registry_GetTexture( entity->textureRef ); assert( texture ); textureIndex = texture->drawIndex % BUFFER_COUNT; texId = texture->texId[textureIndex]; glBindTexture( GL_TEXTURE_2D, texId ); if ( texId ) { assert( texture->texWidth[textureIndex] ); assert( texture->texHeight[textureIndex] ); uScale = (float)texture->width / texture->texWidth[textureIndex]; vScale = (float)texture->height / texture->texHeight[textureIndex]; glUniform4f( s_ent.shader.uColor, uScale, vScale, 1.0f, 1.0f ); } else { glUniform4f( s_ent.shader.uColor, 1.0f, 1.0f, 1.0f, 1.0f ); } if ( texture->format == SxTextureFormat_R8G8B8A8 || texture->format == SxTextureFormat_R8G8B8A8_SRGB ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } } else { glBindTexture( GL_TEXTURE_2D, 0 ); glUniform4f( s_ent.shader.uColor, 1.0f, 1.0f, 1.0f, 1.0f ); glDisable( GL_BLEND ); } indexOffset = 0; triCount = geometry->indexCounts[geometryIndex] / 3; triCountLeft = triCount; while ( triCountLeft ) { #if USE_SPLIT_DRAW batchTriCount = S_Min( triCountLeft, S_Max( 1, triCount / 10 ) ); #else // #if USE_SPLIT_DRAW batchTriCount = triCount; #endif // #else // #if USE_SPLIT_DRAW glDrawElements( GL_TRIANGLES, batchTriCount * 3, GL_UNSIGNED_SHORT, (void *)indexOffset ); indexOffset += batchTriCount * sizeof( ushort ) * 3; triCountLeft -= batchTriCount; } glBindVertexArrayOES_( 0 ); glBindTexture( GL_TEXTURE_2D, 0 ); glDisable( GL_BLEND ); OVR::GL_CheckErrors( "after Entity_DrawEntity" ); Prof_Stop( PROF_DRAW_ENTITY ); }