diff options
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llcubemap.cpp | 14 | ||||
-rw-r--r-- | indra/llrender/llgl.cpp | 111 | ||||
-rw-r--r-- | indra/llrender/llgl.h | 12 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 12 | ||||
-rw-r--r-- | indra/llrender/llglslshader.h | 3 | ||||
-rw-r--r-- | indra/llrender/llpostprocess.cpp | 22 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 338 | ||||
-rw-r--r-- | indra/llrender/llrender.h | 42 | ||||
-rw-r--r-- | indra/llrender/llrendersphere.cpp | 97 | ||||
-rw-r--r-- | indra/llrender/llrendersphere.h | 5 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 18 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 476 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 13 |
13 files changed, 851 insertions, 312 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 1b10354c22..5eb29efbfa 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -273,10 +273,10 @@ void LLCubeMap::setMatrix(S32 stage) LLMatrix4 trans(mat3); trans.transpose(); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glLoadMatrixf((F32 *)trans.mMatrix); - glMatrixMode(GL_MODELVIEW); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.pushMatrix(); + gGL.loadMatrix((F32 *)trans.mMatrix); + gGL.matrixMode(LLRender::MM_MODELVIEW); /*if (stage > 0) { @@ -292,9 +292,9 @@ void LLCubeMap::restoreMatrix() { gGL.getTexUnit(mMatrixStage)->activate(); } - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); /*if (mMatrixStage > 0) { diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 4e3cfb9c8a..1667afe179 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -582,6 +582,8 @@ bool LLGLManager::initGL() glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); } + //HACK always disable texture multisample, use FXAA instead + mHasTextureMultisample = FALSE; #if LL_WINDOWS if (mIsATI) { //using multisample textures on ATI results in black screen for some reason @@ -1193,7 +1195,7 @@ void rotate_quat(LLQuaternion& rotation) { F32 angle_radians, x, y, z; rotation.getAngleAxis(&angle_radians, &x, &y, &z); - glRotatef(angle_radians * RAD_TO_DEG, x, y, z); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); } void flush_glerror() @@ -1329,8 +1331,6 @@ void LLGLState::initClass() sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; glDisable(GL_MULTISAMPLE_ARB); - - glEnableClientState(GL_VERTEX_ARRAY); } //static @@ -1604,7 +1604,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { - if (!gDebugGL) + if (!gDebugGL || LLGLSLShader::sNoFixedFunction) { return; } @@ -1661,7 +1661,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) }; - for (S32 j = 0; j < 4; j++) + for (S32 j = 1; j < 4; j++) { if (glIsEnabled(value[j])) { @@ -1875,79 +1875,6 @@ void LLGLManager::initGLStates() //////////////////////////////////////////////////////////////////////////////// -void enable_vertex_weighting(const S32 index) -{ -#if GL_ARB_vertex_program - if (index > 0) glEnableVertexAttribArrayARB(index); // vertex weights -#endif -} - -void disable_vertex_weighting(const S32 index) -{ -#if GL_ARB_vertex_program - if (index > 0) glDisableVertexAttribArrayARB(index); // vertex weights -#endif -} - -void enable_binormals(const S32 index) -{ -#if GL_ARB_vertex_program - if (index > 0) - { - glEnableVertexAttribArrayARB(index); // binormals - } -#endif -} - -void disable_binormals(const S32 index) -{ -#if GL_ARB_vertex_program - if (index > 0) - { - glDisableVertexAttribArrayARB(index); // binormals - } -#endif -} - - -void enable_cloth_weights(const S32 index) -{ -#if GL_ARB_vertex_program - if (index > 0) glEnableVertexAttribArrayARB(index); -#endif -} - -void disable_cloth_weights(const S32 index) -{ -#if GL_ARB_vertex_program - if (index > 0) glDisableVertexAttribArrayARB(index); -#endif -} - -void set_vertex_weights(const S32 index, const U32 stride, const F32 *weights) -{ -#if GL_ARB_vertex_program - if (index > 0) glVertexAttribPointerARB(index, 1, GL_FLOAT, FALSE, stride, weights); - stop_glerror(); -#endif -} - -void set_vertex_clothing_weights(const S32 index, const U32 stride, const LLVector4 *weights) -{ -#if GL_ARB_vertex_program - if (index > 0) glVertexAttribPointerARB(index, 4, GL_FLOAT, TRUE, stride, weights); - stop_glerror(); -#endif -} - -void set_binormals(const S32 index, const U32 stride,const LLVector3 *binormals) -{ -#if GL_ARB_vertex_program - if (index > 0) glVertexAttribPointerARB(index, 3, GL_FLOAT, FALSE, stride, binormals); - stop_glerror(); -#endif -} - void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ) { // GL_VERSION returns a null-terminated string with the format: @@ -2060,20 +1987,20 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) glh::matrix4f suffix; suffix.set_row(2, cplane); glh::matrix4f newP = suffix * P; - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(newP.m); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(newP.m); gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m); - glMatrixMode(GL_MODELVIEW); + gGL.matrixMode(LLRender::MM_MODELVIEW); } LLGLUserClipPlane::~LLGLUserClipPlane() { if (mApply) { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); } } @@ -2263,16 +2190,16 @@ LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer) P.element(2, i) = P.element(3, i) * depth; } - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(P.m); - glMatrixMode(GL_MODELVIEW); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(P.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); } LLGLSquashToFarClip::~LLGLSquashToFarClip() { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index d736133f3f..495e523c31 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -252,7 +252,7 @@ public: static void dumpStates(); static void checkStates(const std::string& msg = ""); static void checkTextureChannels(const std::string& msg = ""); - static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0x0001); + static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0); protected: static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap; @@ -419,15 +419,7 @@ extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" void init_glstates(); -void enable_vertex_weighting(const S32 index); -void disable_vertex_weighting(const S32 index); -void enable_binormals(const S32 index); -void disable_binormals(const S32 index); -void enable_cloth_weights(const S32 index); -void disable_cloth_weights(const S32 index); -void set_vertex_weights(const S32 index, const U32 stride, const F32 *weights); -void set_vertex_clothing_weights(const S32 index, const U32 stride, const LLVector4 *weights); -void set_binormals(const S32 index, const U32 stride, const LLVector3 *binormals); + void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ); extern BOOL gClothRipple; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index f51d83abe4..95ce227171 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -31,6 +31,7 @@ #include "llshadermgr.h" #include "llfile.h" #include "llrender.h" +#include "llvertexbuffer.h" #if LL_DARWIN #include "OpenGL/OpenGL.h" @@ -75,6 +76,10 @@ hasAlphaMask(false) LLGLSLShader::LLGLSLShader() : mProgramObject(0), mActiveTextureChannels(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE) { + for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) + { + mMatHash[i] = 0xFFFFFFFF; + } } void LLGLSLShader::unload() @@ -116,10 +121,12 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, // Create program mProgramObject = glCreateProgramObjectARB(); +#if !LL_DARWIN if (gGLManager.mGLVersion < 3.1f) { //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support) mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } +#endif // !LL_DARWIN //compile new source vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); @@ -386,6 +393,7 @@ void LLGLSLShader::bind() gGL.flush(); if (gGLManager.mHasShaderObjects) { + LLVertexBuffer::unbind(); glUseProgramObjectARB(mProgramObject); sCurBoundShader = mProgramObject; sCurBoundShaderPtr = this; @@ -411,6 +419,7 @@ void LLGLSLShader::unbind() stop_glerror(); } } + LLVertexBuffer::unbind(); glUseProgramObjectARB(0); sCurBoundShader = 0; sCurBoundShaderPtr = NULL; @@ -420,6 +429,7 @@ void LLGLSLShader::unbind() void LLGLSLShader::bindNoShader(void) { + LLVertexBuffer::unbind(); glUseProgramObjectARB(0); sCurBoundShader = 0; sCurBoundShaderPtr = NULL; @@ -930,7 +940,9 @@ void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v std::map<GLint, LLVector4>::iterator iter = mValue.find(location); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { + stop_glerror(); glUniform4fvARB(location, count, v); + stop_glerror(); mValue[location] = vec; } } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 558ea66b50..c1765e2701 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -117,7 +117,6 @@ public: GLint getAttribLocation(U32 attrib); GLint mapUniformTextureChannel(GLint location, GLenum type); - //enable/disable texture channel for specified uniform //if given texture uniform is active in the shader, //the corresponding channel will be active upon return @@ -132,6 +131,8 @@ public: // Unbinds any previously bound shader by explicitly binding no shader. static void bindNoShader(void); + U32 mMatHash[LLRender::NUM_MATRIX_MODES]; + GLhandleARB mProgramObject; std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index d76b2d9004..c0045c8044 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -466,21 +466,21 @@ void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadT void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f ); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f ); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); } void LLPostProcess::viewPerspective(void) { - glMatrixMode( GL_PROJECTION ); - glPopMatrix(); - glMatrixMode( GL_MODELVIEW ); - glPopMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); } void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index edcc47aa14..359e6fd560 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -951,6 +951,15 @@ LLRender::LLRender() mCurrBlendAlphaSFactor = BF_UNDEF; mCurrBlendColorDFactor = BF_UNDEF; mCurrBlendAlphaDFactor = BF_UNDEF; + + mMatrixMode = LLRender::MM_MODELVIEW; + + for (U32 i = 0; i < NUM_MATRIX_MODES; ++i) + { + mMatIdx[i] = 0; + mMatHash[i] = 0; + mCurMatHash[i] = 0xFFFFFFFF; + } } LLRender::~LLRender() @@ -1007,28 +1016,262 @@ void LLRender::refreshState(void) mDirty = false; } +void LLRender::syncMatrices() +{ + stop_glerror(); + + GLenum mode[] = + { + GL_MODELVIEW, + GL_PROJECTION, + GL_TEXTURE, + GL_TEXTURE, + GL_TEXTURE, + GL_TEXTURE, + }; + + std::string name[] = + { + "modelview_matrix", + "projection_matrix", + "texture_matrix0", + "texture_matrix1", + "texture_matrix2", + "texture_matrix3", + }; + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + if (shader) + { + + llassert(shader); + + bool do_normal = false; + bool do_mvp = false; + + for (U32 i = 0; i < NUM_MATRIX_MODES; ++i) + { + if (mMatHash[i] != shader->mMatHash[i]) + { + shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m); + shader->mMatHash[i] = mMatHash[i]; + + if (i == MM_MODELVIEW) + { + do_normal = true; + do_mvp = true; + } + else if (i == MM_PROJECTION) + { + do_mvp = true; + } + } + } + + if (do_normal) + { + S32 loc = shader->getUniformLocation("normal_matrix"); + if (loc > -1) + { + U32 i = MM_MODELVIEW; + + glh::matrix4f norm = mMatrix[i][mMatIdx[i]].inverse().transpose(); + + F32 norm_mat[] = + { + norm.m[0], norm.m[1], norm.m[2], + norm.m[4], norm.m[5], norm.m[6], + norm.m[8], norm.m[9], norm.m[10] + }; + + shader->uniformMatrix3fv("normal_matrix", 1, GL_FALSE, norm_mat); + } + } + + if (do_mvp) + { + S32 loc = shader->getUniformLocation("modelview_projection_matrix"); + if (loc > -1) + { + U32 mv = MM_MODELVIEW; + U32 proj = MM_PROJECTION; + + glh::matrix4f mvp = mMatrix[mv][mMatIdx[mv]]; + mvp.mult_left(mMatrix[proj][mMatIdx[proj]]); + + shader->uniformMatrix4fv("modelview_projection_matrix", 1, GL_FALSE, mvp.m); + } + } + } + else + { + for (U32 i = 0; i < 2; ++i) + { + if (mMatHash[i] != mCurMatHash[i]) + { + glMatrixMode(mode[i]); + glLoadMatrixf(mMatrix[i][mMatIdx[i]].m); + mCurMatHash[i] = mMatHash[i]; + } + } + + for (U32 i = 2; i < NUM_MATRIX_MODES; ++i) + { + if (mMatHash[i] != mCurMatHash[i]) + { + gGL.getTexUnit(i-2)->activate(); + glMatrixMode(mode[i]); + glLoadMatrixf(mMatrix[i][mMatIdx[i]].m); + mCurMatHash[i] = mMatHash[i]; + } + } + } + + stop_glerror(); +} + void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) { flush(); - glTranslatef(x,y,z); + + glh::matrix4f trans_mat(1,0,0,x, + 0,1,0,y, + 0,0,1,z, + 0,0,0,1); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat); + mMatHash[mMatrixMode]++; } void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z) { flush(); - glScalef(x,y,z); + + glh::matrix4f scale_mat(x,0,0,0, + 0,y,0,0, + 0,0,z,0, + 0,0,0,1); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat); + mMatHash[mMatrixMode]++; +} + +void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar) +{ + flush(); + + glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left), + 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom), + 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear), + 0,0,0,1); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat); + mMatHash[mMatrixMode]++; +} + +void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z) +{ + flush(); + + F32 r = a * DEG_TO_RAD; + + F32 c = cosf(r); + F32 s = sinf(r); + + F32 ic = 1.f-c; + + glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0, + x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0, + x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0, + 0,0,0,1); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat); + mMatHash[mMatrixMode]++; } void LLRender::pushMatrix() { flush(); - glPushMatrix(); + + if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1) + { + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]]; + ++mMatIdx[mMatrixMode]; + } + else + { + llwarns << "Matrix stack overflow." << llendl; + } } void LLRender::popMatrix() { flush(); - glPopMatrix(); + if (mMatIdx[mMatrixMode] > 0) + { + --mMatIdx[mMatrixMode]; + mMatHash[mMatrixMode]++; + } + else + { + llwarns << "Matrix stack underflow." << llendl; + } +} + +void LLRender::loadMatrix(const GLfloat* m) +{ + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m); + mMatHash[mMatrixMode]++; +} + +void LLRender::loadMatrix(const GLdouble* dm) +{ + F32 m[16]; + for (U32 i = 0; i < 16; i++) + { + m[i] = (F32) dm[i]; + } + + loadMatrix(m); +} + +void LLRender::multMatrix(const GLfloat* m) +{ + flush(); + + glh::matrix4f mat((GLfloat*) m); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat); + mMatHash[mMatrixMode]++; +} + +void LLRender::matrixMode(U32 mode) +{ + if (mode == MM_TEXTURE) + { + mode = MM_TEXTURE0 + gGL.getCurrentTexUnitIndex(); + } + + llassert(mode < NUM_MATRIX_MODES); + mMatrixMode = mode; +} + +void LLRender::multMatrix(const GLdouble* dm) +{ + F32 m[16]; + for (U32 i = 0; i < 16; i++) + { + m[i] = (F32) dm[i]; + } + + multMatrix(m); +} + +void LLRender::loadIdentity() +{ + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity(); + mMatHash[mMatrixMode]++; } void LLRender::translateUI(F32 x, F32 y, F32 z) @@ -1421,12 +1664,16 @@ void LLRender::flush() } } + //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) + U32 count = mCount; + mCount = 0; + mBuffer->setBuffer(immediate_mask); - mBuffer->drawArrays(mMode, 0, mCount); + mBuffer->drawArrays(mMode, 0, count); - mVerticesp[0] = mVerticesp[mCount]; - mTexcoordsp[0] = mTexcoordsp[mCount]; - mColorsp[0] = mColorsp[mCount]; + mVerticesp[0] = mVerticesp[count]; + mTexcoordsp[0] = mTexcoordsp[count]; + mColorsp[0] = mColorsp[count]; mCount = 0; } } @@ -1586,6 +1833,81 @@ void LLRender::color3fv(const GLfloat* c) color4f(c[0],c[1],c[2],1); } +void LLRender::diffuseColor3f(F32 r, F32 g, F32 b) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + + if (shader) + { + shader->uniform4f("color", r,g,b,1.f); + } + else + { + glColor3f(r,g,b); + } +} + +void LLRender::diffuseColor3fv(const F32* c) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + + if (shader) + { + shader->uniform4f("color", c[0], c[1], c[2], 1.f); + } + else + { + glColor3fv(c); + } +} + +void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + + if (shader) + { + shader->uniform4f("color", r,g,b,a); + } + else + { + glColor4f(r,g,b,a); + } +} + +void LLRender::diffuseColor4fv(const F32* c) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + + if (shader) + { + shader->uniform4fv("color", 1, c); + } + else + { + glColor4fv(c); + } +} + +void LLRender::diffuseColor4ubv(const U8* c) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + + if (shader) + { + shader->uniform4f("color", c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f); + } + else + { + glColor4ubv(c); + } +} + void LLRender::debugTexUnits(void) { LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 8f7ee30d87..465c16f0de 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -41,6 +41,8 @@ #include "llstrider.h" #include "llpointer.h" #include "llglheaders.h" +#include "llmatrix4a.h" +#include "glh/glh_linear.h" class LLVertexBuffer; class LLCubeMap; @@ -48,6 +50,8 @@ class LLImageGL; class LLRenderTarget; class LLTexture ; +#define LL_MATRIX_STACK_DEPTH 32 + class LLTexUnit { friend class LLRender; @@ -308,6 +312,18 @@ public: BF_UNDEF } eBlendFactor; + typedef enum + { + MM_MODELVIEW = 0, + MM_PROJECTION, + MM_TEXTURE0, + MM_TEXTURE1, + MM_TEXTURE2, + MM_TEXTURE3, + NUM_MATRIX_MODES, + MM_TEXTURE + } eMatrixMode; + LLRender(); ~LLRender(); void init() ; @@ -319,8 +335,19 @@ public: void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z); void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z); + void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z); + void ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar); + void pushMatrix(); void popMatrix(); + void loadMatrix(const GLfloat* m); + void loadMatrix(const GLdouble* m); + void loadIdentity(); + void multMatrix(const GLfloat* m); + void multMatrix(const GLdouble* m); + void matrixMode(U32 mode); + + void syncMatrices(); void translateUI(F32 x, F32 y, F32 z); void scaleUI(F32 x, F32 y, F32 z); @@ -351,6 +378,12 @@ public: void color3fv(const GLfloat* c); void color4ubv(const GLubyte* c); + void diffuseColor3f(F32 r, F32 g, F32 b); + void diffuseColor3fv(const F32* c); + void diffuseColor4f(F32 r, F32 g, F32 b, F32 a); + void diffuseColor4fv(const F32* c); + void diffuseColor4ubv(const U8* c); + void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count); void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count); void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); @@ -391,7 +424,14 @@ public: static U32 sUIVerts; private: - bool mDirty; + U32 mMatrixMode; + U32 mMatIdx[NUM_MATRIX_MODES]; + U32 mMatHash[NUM_MATRIX_MODES]; + glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH]; + + U32 mCurMatHash[NUM_MATRIX_MODES]; + + bool mDirty; U32 mCount; U32 mMode; U32 mCurrTextureUnitIndex; diff --git a/indra/llrender/llrendersphere.cpp b/indra/llrender/llrendersphere.cpp index a5cd70445f..e7e07a1ab2 100644 --- a/indra/llrender/llrendersphere.cpp +++ b/indra/llrender/llrendersphere.cpp @@ -35,106 +35,11 @@ #include "llglheaders.h" -GLUquadricObj *gQuadObj2 = NULL; LLRenderSphere gSphere; -void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks); - -void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks) -{ - if (!gQuadObj2) - { - gQuadObj2 = gluNewQuadric(); - if (!gQuadObj2) - { - llwarns << "drawSolidSphere couldn't allocate quadric" << llendl; - return; - } - } - - gluQuadricDrawStyle(gQuadObj2, GLU_FILL); - gluQuadricNormals(gQuadObj2, GLU_SMOOTH); - // If we ever changed/used the texture or orientation state - // of quadObj, we'd need to change it to the defaults here - // with gluQuadricTexture and/or gluQuadricOrientation. - gluQuadricTexture(gQuadObj2, GL_TRUE); - gluSphere(gQuadObj2, radius, slices, stacks); -} - - -// A couple thoughts on sphere drawing: -// 1) You need more slices than stacks, but little less than 2:1 -// 2) At low LOD, setting stacks to an odd number avoids a "band" around the equator, making things look smoother -void LLRenderSphere::prerender() -{ - // Create a series of display lists for different LODs - mDList[0] = glGenLists(1); - glNewList(mDList[0], GL_COMPILE); - drawSolidSphere(1.0, 30, 20); - glEndList(); - - mDList[1] = glGenLists(1); - glNewList(mDList[1], GL_COMPILE); - drawSolidSphere(1.0, 20, 15); - glEndList(); - - mDList[2] = glGenLists(1); - glNewList(mDList[2], GL_COMPILE); - drawSolidSphere(1.0, 12, 8); - glEndList(); - - mDList[3] = glGenLists(1); - glNewList(mDList[3], GL_COMPILE); - drawSolidSphere(1.0, 8, 5); - glEndList(); -} - -void LLRenderSphere::cleanupGL() -{ - for (S32 detail = 0; detail < 4; detail++) - { - glDeleteLists(mDList[detail], 1); - mDList[detail] = 0; - } - - if (gQuadObj2) - { - gluDeleteQuadric(gQuadObj2); - gQuadObj2 = NULL; - } -} - -// Constants here are empirically derived from my eyeballs, JNC -// -// The toughest adjustment is the cutoff for the lowest LOD -// Maybe we should have more LODs at the low end? -void LLRenderSphere::render(F32 pixel_area) -{ - S32 level_of_detail; - - if (pixel_area > 10000.f) - { - level_of_detail = 0; - } - else if (pixel_area > 800.f) - { - level_of_detail = 1; - } - else if (pixel_area > 100.f) - { - level_of_detail = 2; - } - else - { - level_of_detail = 3; - } - glCallList(mDList[level_of_detail]); -} - - void LLRenderSphere::render() { - glCallList(mDList[0]); + renderGGL(); } inline LLVector3 polar_to_cart(F32 latitude, F32 longitude) diff --git a/indra/llrender/llrendersphere.h b/indra/llrender/llrendersphere.h index 96a6bec80c..f8e9e86e7f 100644 --- a/indra/llrender/llrendersphere.h +++ b/indra/llrender/llrendersphere.h @@ -40,11 +40,6 @@ void lat2xyz(LLVector3 * result, F32 lat, F32 lon); // utility routine class LLRenderSphere { public: - LLGLuint mDList[5]; - - void prerender(); - void cleanupGL(); - void render(F32 pixel_area); // of a box of size 1.0 at that position void render(); // render at highest LOD void renderGGL(); // render using LLRender diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 986c1f2774..db3d7becd9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -531,9 +531,9 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } //we can't have any lines longer than 1024 characters - //or any shaders longer than 1024 lines... deal - DaveP + //or any shaders longer than 4096 lines... deal - DaveP GLcharARB buff[1024]; - GLcharARB* text[1024]; + GLcharARB* text[4096]; GLuint count = 0; if (gGLManager.mGLVersion < 2.1f) @@ -544,10 +544,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //set version to 1.20 text[count++] = strdup("#version 120\n"); + text[count++] = strdup("#define FXAA_GLSL_120 1\n"); + text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); } else { //set version to 1.30 text[count++] = strdup("#version 130\n"); + text[count++] = strdup("#define FXAA_GLSL_130 1\n"); } //copy preprocessor definitions into buffer @@ -649,7 +652,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } //copy file into memory - while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) ) + while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(text) ) { text[count++] = (GLcharARB *)strdup((char *)buff); } @@ -704,14 +707,23 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; dumpObjectLog(ret); +#if LL_WINDOWS std::stringstream ostr; //dump shader source for debugging for (GLuint i = 0; i < count; i++) { ostr << i << ": " << text[i]; + + if (i % 128 == 0) + { //dump every 128 lines + LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl; + ostr = std::stringstream(); + } + } LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl; +#endif // LL_WINDOWS ret = 0; } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 8fd1193780..090da765ac 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -63,11 +63,8 @@ U32 LLVertexBuffer::sAllocatedBytes = 0; BOOL LLVertexBuffer::sMapped = FALSE; BOOL LLVertexBuffer::sUseStreamDraw = TRUE; BOOL LLVertexBuffer::sPreferStreamDraw = FALSE; -S32 LLVertexBuffer::sWeight4Loc = -1; - std::vector<U32> LLVertexBuffer::sDeleteList; - const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms class LLGLSyncFence : public LLGLFence @@ -131,6 +128,7 @@ S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = sizeof(LLVector2), // TYPE_TEXCOORD2, sizeof(LLVector2), // TYPE_TEXCOORD3, sizeof(LLColor4U), // TYPE_COLOR, + sizeof(U8), // TYPE_EMISSIVE sizeof(LLVector4), // TYPE_BINORMAL, sizeof(F32), // TYPE_WEIGHT, sizeof(LLVector4), // TYPE_WEIGHT4, @@ -149,6 +147,7 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = GL_LINE_LOOP, }; + //static void LLVertexBuffer::setupClientArrays(U32 data_mask) { @@ -157,36 +156,79 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) llerrs << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl; }*/ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + if (sLastMask != data_mask) { + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + static LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(sLastMask == 0 || last_shader == shader); + last_shader = shader; + U32 mask[] = { MAP_VERTEX, MAP_NORMAL, MAP_TEXCOORD0, MAP_COLOR, + MAP_EMISSIVE, + MAP_WEIGHT, + MAP_WEIGHT4, + MAP_BINORMAL, + MAP_CLOTHWEIGHT, }; + U32 type[] = + { + TYPE_VERTEX, + TYPE_NORMAL, + TYPE_TEXCOORD0, + TYPE_COLOR, + TYPE_EMISSIVE, + TYPE_WEIGHT, + TYPE_WEIGHT4, + TYPE_BINORMAL, + TYPE_CLOTHWEIGHT, + }; + GLenum array[] = { GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY, + 0, + 0, + 0, + 0, + 0, }; BOOL error = FALSE; - for (U32 i = 0; i < 4; ++i) + for (U32 i = 0; i < 9; ++i) { + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(type[i]); + } + if (sLastMask & mask[i]) { //was enabled - if (!(data_mask & mask[i]) && i > 0) + if (!(data_mask & mask[i])) { //needs to be disabled - glDisableClientState(array[i]); + if (loc >= 0) + { + glDisableVertexAttribArrayARB(loc); + } + else if (!shader) + { + glDisableClientState(array[i]); + } } - else if (gDebugGL) - { //needs to be enabled, make sure it was (DEBUG TEMPORARY) - if (i > 0 && !glIsEnabled(array[i])) + else if (gDebugGL && !shader && array[i]) + { //needs to be enabled, make sure it was (DEBUG) + if (loc < 0 && !glIsEnabled(array[i])) { if (gDebugSession) { @@ -202,11 +244,18 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } else { //was disabled - if (data_mask & mask[i] && i > 0) + if (data_mask & mask[i]) { //needs to be enabled - glEnableClientState(array[i]); + if (loc >= 0) + { + glEnableVertexAttribArrayARB(loc); + } + else if (!shader) + { + glEnableClientState(array[i]); + } } - else if (gDebugGL && i > 0 && glIsEnabled(array[i])) + else if (!shader && array[i] && gDebugGL && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) if (gDebugSession) { @@ -233,62 +282,71 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) MAP_TEXCOORD3 }; + U32 type_tc[] = + { + TYPE_TEXCOORD1, + TYPE_TEXCOORD2, + TYPE_TEXCOORD3 + }; + for (U32 i = 0; i < 3; i++) { + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(type_tc[i]); + } + if (sLastMask & map_tc[i]) { if (!(data_mask & map_tc[i])) - { - glClientActiveTextureARB(GL_TEXTURE1_ARB+i); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + { //disable + if (loc >= 0) + { + glDisableVertexAttribArrayARB(loc); + } + else if (!shader) + { + glClientActiveTextureARB(GL_TEXTURE1_ARB+i); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } } else if (data_mask & map_tc[i]) { - glClientActiveTextureARB(GL_TEXTURE1_ARB+i); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + if (loc >= 0) + { + glEnableVertexAttribArrayARB(loc); + } + else if (!shader) + { + glClientActiveTextureARB(GL_TEXTURE1_ARB+i); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } } - if (sLastMask & MAP_BINORMAL) + if (!shader) { - if (!(data_mask & MAP_BINORMAL)) + if (sLastMask & MAP_BINORMAL) { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + if (!(data_mask & MAP_BINORMAL)) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } - } - else if (data_mask & MAP_BINORMAL) - { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - - if (sLastMask & MAP_WEIGHT4) - { - if (sWeight4Loc < 0) + else if (data_mask & MAP_BINORMAL) { - llerrs << "Weighting disabled but vertex buffer still bound!" << llendl; - } - - if (!(data_mask & MAP_WEIGHT4)) - { //disable 4-component skin weight - glDisableVertexAttribArrayARB(sWeight4Loc); - } - } - else if (data_mask & MAP_WEIGHT4) - { - if (sWeight4Loc >= 0) - { //enable 4-component skin weight - glEnableVertexAttribArrayARB(sWeight4Loc); + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(GL_TEXTURE0_ARB); } } - - + sLastMask = data_mask; } } @@ -296,6 +354,9 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) //static void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) { + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + gGL.syncMatrices(); + U32 count = pos.size(); llassert_always(norm.size() >= pos.size()); llassert_always(count > 0) ; @@ -304,12 +365,75 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con setupClientArrays(MAP_VERTEX | MAP_NORMAL); - glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); - glNormalPointer(GL_FLOAT, 0, norm[0].mV); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + if (shader) + { + S32 loc = shader->getAttribLocation(LLVertexBuffer::TYPE_VERTEX); + if (loc > -1) + { + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV); + } + loc = shader->getAttribLocation(LLVertexBuffer::TYPE_NORMAL); + if (loc > -1) + { + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV); + } + } + else + { + glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); + glNormalPointer(GL_FLOAT, 0, norm[0].mV); + } glDrawArrays(sGLMode[mode], 0, count); } +//static +void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp) +{ + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + + gGL.syncMatrices(); + + U32 mask = LLVertexBuffer::MAP_VERTEX; + if (tc) + { + mask = mask | LLVertexBuffer::MAP_TEXCOORD0; + } + + unbind(); + + setupClientArrays(mask); + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + if (shader) + { + S32 loc = shader->getAttribLocation(LLVertexBuffer::TYPE_VERTEX); + if (loc > -1) + { + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos); + + if (tc) + { + loc = shader->getAttribLocation(LLVertexBuffer::TYPE_TEXCOORD0); + if (loc > -1) + { + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc); + } + } + } + } + else + { + glTexCoordPointer(2, GL_FLOAT, 0, tc); + glVertexPointer(3, GL_FLOAT, 16, pos); + } + + glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp); +} + void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const { if (start >= (U32) mRequestedNumVerts || @@ -343,7 +467,10 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi { validateRange(start, end, count, indices_offset); + gGL.syncMatrices(); + llassert(mRequestedNumVerts >= 0); + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); if (mGLIndices != sGLRenderIndices) { @@ -372,6 +499,10 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + + gGL.syncMatrices(); + llassert(mRequestedNumIndices >= 0); if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) @@ -404,6 +535,10 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + + gGL.syncMatrices(); + llassert(mRequestedNumVerts >= 0); if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) @@ -1601,6 +1736,10 @@ bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S { return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range); } +bool LLVertexBuffer::getEmissiveStrider(LLStrider<U8>& strider, S32 index, S32 count, bool map_range) +{ + return VertexBufferStrider<U8,TYPE_EMISSIVE>::get(*this, strider, index, count, map_range); +} bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range) { return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range); @@ -1625,6 +1764,34 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) //set up pointers if the data mask is different ... BOOL setup = (sLastMask != data_mask); + if (gDebugGL && data_mask != 0) + { + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + if (shader) + { + U32 required_mask = 0; + for (U32 i = 0; i < LLVertexBuffer::TYPE_MAX; ++i) + { + if (shader->getAttribLocation(i) > -1) + { + U32 required = 1 << i; + if ((data_mask & required) == 0) + { + llwarns << "Missing attribute: " << i << llendl; + } + + required_mask |= required; + + } + } + + if ((data_mask & required_mask) != required_mask) + { + llerrs << "Shader consumption mismatches data provision." << llendl; + } + } + } + if (useVBOs()) { if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)) @@ -1819,66 +1986,223 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; } + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + //assert that fixed function is allowed OR a shader is currently bound + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + if (data_mask & MAP_NORMAL) { - glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_NORMAL); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + } + else if (!shader) + { + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); + } } if (data_mask & MAP_TEXCOORD3) { - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_TEXCOORD3); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); + } + else if (!shader) + { + glClientActiveTextureARB(GL_TEXTURE3_ARB); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } if (data_mask & MAP_TEXCOORD2) { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_TEXCOORD2); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); + } + else if (!shader) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } if (data_mask & MAP_TEXCOORD1) { - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_TEXCOORD1); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); + } + else if (!shader) + { + glClientActiveTextureARB(GL_TEXTURE1_ARB); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } if (data_mask & MAP_BINORMAL) { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_BINORMAL); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); + } + else if (!shader) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } } if (data_mask & MAP_TEXCOORD0) { - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_TEXCOORD0); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + } + else if (!shader) + { + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + } } if (data_mask & MAP_COLOR) { - glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_COLOR); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); + } + else if (!shader) + { + glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); + } + } + if (data_mask & MAP_EMISSIVE) + { + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_EMISSIVE); + } + + if (loc >= 0) + { + glVertexAttribPointerARB(loc, 1, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], (void*)(base + mOffsets[TYPE_EMISSIVE])); + } } - if (data_mask & MAP_WEIGHT) { - glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_WEIGHT); + } + + if (loc < 0) + { //legacy behavior, some shaders have weight hardcoded to location 1 + loc = 1; + } + + glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); + } - if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) + if (data_mask & MAP_WEIGHT4) { - glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); + if (shader) + { + S32 loc = shader->getAttribLocation(TYPE_WEIGHT4); + if (loc > -1) + { + glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); + } + } } if (data_mask & MAP_CLOTHWEIGHT) { - glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + S32 loc = -1; + if (shader) + { + loc = shader->getAttribLocation(TYPE_CLOTHWEIGHT); + } + + if (loc < 0) + { //legacy behavior, some shaders have weight hardcoded to location 4 + loc = 4; + } + glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } if (data_mask & MAP_VERTEX) { - if (data_mask & MAP_TEXTURE_INDEX) + S32 loc = -1; + if (shader) { - glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + loc = shader->getAttribLocation(TYPE_VERTEX); } - else + + if (loc >= 0) { - glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + if (data_mask & MAP_TEXTURE_INDEX) + { + glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } + else + { + glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } + } + else if (!shader) + { + if (data_mask & MAP_TEXTURE_INDEX) + { + glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } + else + { + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } } } diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 578cec3885..7aa5928524 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -111,8 +111,6 @@ public: static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; - static S32 sWeight4Loc; - static BOOL sUseStreamDraw; static BOOL sPreferStreamDraw; @@ -120,6 +118,7 @@ public: static void cleanupClass(); static void setupClientArrays(U32 data_mask); static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); + static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); static void clientCopy(F64 max_time = 0.005); //copy data from client to GL static void unbind(); //unbind any bound vertex buffer @@ -133,6 +132,12 @@ public: static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices); + //WARNING -- when updating these enums you MUST + // 1 - update LLVertexBuffer::sTypeSize + // 2 - add a strider accessor + // 3 - modify LLVertexBuffer::setupVertexBuffer + // 4 - modify LLVertexBuffer::setupClientArray + // 5 - modify LLViewerShaderMgr::mReservedAttribs enum { TYPE_VERTEX, TYPE_NORMAL, @@ -141,6 +146,7 @@ public: TYPE_TEXCOORD2, TYPE_TEXCOORD3, TYPE_COLOR, + TYPE_EMISSIVE, // These use VertexAttribPointer and should possibly be made generic TYPE_BINORMAL, TYPE_WEIGHT, @@ -160,6 +166,7 @@ public: MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2), MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3), MAP_COLOR = (1<<TYPE_COLOR), + MAP_EMISSIVE = (1<<TYPE_EMISSIVE), // These use VertexAttribPointer and should possibly be made generic MAP_BINORMAL = (1<<TYPE_BINORMAL), MAP_WEIGHT = (1<<TYPE_WEIGHT), @@ -218,10 +225,12 @@ public: bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getEmissiveStrider(LLStrider<U8>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); + BOOL isEmpty() const { return mEmpty; } BOOL isLocked() const { return mVertexLocked || mIndexLocked; } S32 getNumVerts() const { return mNumVerts; } |