00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "stdopengl.h"
00029
00030 #include "3d/primitive_block.h"
00031 #include "3d/vertex_program.h"
00032 #include "3d/vertex_program_parse.h"
00033 #include <algorithm>
00034
00035
00036 using namespace std;
00037 using namespace NLMISC;
00038
00039
00040 namespace NL3D
00041 {
00042
00043
00044 CVertexProgamDrvInfosGL::CVertexProgamDrvInfosGL (CDriverGL *drv, ItVtxPrgDrvInfoPtrList it) : IVertexProgramDrvInfos (drv, it)
00045 {
00046
00047 nlassert (drv->_Extensions.NVVertexProgram
00048 || drv->_Extensions.EXTVertexShader
00049 );
00050
00051 if (drv->_Extensions.NVVertexProgram)
00052 {
00053
00054 nglGenProgramsNV (1, &ID);
00055 }
00056 else
00057 {
00058 ID = nglGenVertexShadersEXT(1);
00059 }
00060 }
00061
00062
00063
00064 bool CDriverGL::isVertexProgramSupported () const
00065 {
00066 return _Extensions.NVVertexProgram || _Extensions.EXTVertexShader;
00067 }
00068
00069
00070 bool CDriverGL::isVertexProgramEmulated () const
00071 {
00072 return _Extensions.NVVertexProgramEmulated;
00073 }
00074
00075
00076
00077
00078 bool CDriverGL::activeNVVertexProgram (CVertexProgram *program)
00079 {
00080
00081 if (program)
00082 {
00083
00084 glEnable (GL_VERTEX_PROGRAM_NV);
00085 _VertexProgramEnabled= true;
00086
00087
00088
00089 CVertexProgamDrvInfosGL *drvInfo;
00090
00091
00092 if (program->_DrvInfo==NULL)
00093 {
00097 CVPParser parser;
00098 CVPParser::TProgram parsedProgram;
00099 std::string errorOutput;
00100 bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
00101 if (!result)
00102 {
00103 nlwarning("Unable to parse a vertex program :");
00104 nlwarning(errorOutput.c_str());
00105 #ifdef NL_DEBUG
00106 nlassert(0);
00107 #endif
00108 return false;
00109 }
00110
00111
00112 ItVtxPrgDrvInfoPtrList it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end());
00113
00114
00115 *it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
00116
00117
00118 program->_DrvInfo=drvInfo;
00119
00120
00121 nglLoadProgramNV (GL_VERTEX_PROGRAM_NV, drvInfo->ID, program->getProgram().length(), (const GLubyte*)program->getProgram().c_str());
00122
00123
00124 GLint errorOff;
00125 glGetIntegerv (GL_PROGRAM_ERROR_POSITION_NV, &errorOff);
00126
00127
00128 if (errorOff>=0)
00129 {
00130
00131 uint length = program->getProgram ().length();
00132 const char* sString= program->getProgram ().c_str();
00133
00134
00135 uint line=1;
00136 uint charC=1;
00137
00138
00139 uint offset=0;
00140 while ((offset<length)&&(offset<(uint)errorOff))
00141 {
00142 if (sString[offset]=='\n')
00143 {
00144 line++;
00145 charC=1;
00146 }
00147 else
00148 charC++;
00149
00150
00151 offset++;
00152 }
00153
00154
00155 nlinfo ("Vertex program syntax error line %d character %d\n", line, charC);
00156
00157
00158 glDisable (GL_VERTEX_PROGRAM_NV);
00159 _VertexProgramEnabled= false;
00160
00161
00162 return false;
00163 }
00164
00165
00166 return true;
00167 }
00168 else
00169 {
00170
00171 drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
00172 }
00173
00174
00175 nglBindProgramNV (GL_VERTEX_PROGRAM_NV, drvInfo->ID);
00176 _LastSetuppedVP = program;
00177
00178
00179 return true;
00180 }
00181 else
00182 {
00183
00184 glDisable (GL_VERTEX_PROGRAM_NV);
00185 _VertexProgramEnabled= false;
00186
00187 return true;
00188 }
00189 }
00190
00191
00192
00193 static
00194 inline GLenum convSwizzleToGLFormat(CVPSwizzle::EComp comp, bool negate)
00195 {
00196 if (!negate)
00197 {
00198 switch(comp)
00199 {
00200 case CVPSwizzle::X: return GL_X_EXT;
00201 case CVPSwizzle::Y: return GL_Y_EXT;
00202 case CVPSwizzle::Z: return GL_Z_EXT;
00203 case CVPSwizzle::W: return GL_W_EXT;
00204 default:
00205 nlstop;
00206 return 0;
00207 break;
00208 }
00209 }
00210 else
00211 {
00212 switch(comp)
00213 {
00214 case CVPSwizzle::X: return GL_NEGATIVE_X_EXT;
00215 case CVPSwizzle::Y: return GL_NEGATIVE_Y_EXT;
00216 case CVPSwizzle::Z: return GL_NEGATIVE_Z_EXT;
00217 case CVPSwizzle::W: return GL_NEGATIVE_W_EXT;
00218 default:
00219 nlstop;
00220 return 0;
00221 break;
00222 }
00223 }
00224 }
00225
00226
00229 static GLuint convOutputRegisterToEXTVertexShader(CVPOperand::EOutputRegister r)
00230 {
00231 switch (r)
00232 {
00233 case CVPOperand::OHPosition: return GL_OUTPUT_VERTEX_EXT;
00234 case CVPOperand::OPrimaryColor: return GL_OUTPUT_COLOR0_EXT;
00235 case CVPOperand::OSecondaryColor: return GL_OUTPUT_COLOR1_EXT;
00236 case CVPOperand::OBackFacePrimaryColor:
00237 nlwarning("Backface color used in a vertex program is not supported by device, defaulting to front color");
00238 return GL_OUTPUT_COLOR0_EXT;
00239 break;
00240 case CVPOperand::OBackFaceSecondaryColor:
00241 nlwarning("Backface color used in a vertex program is not supported by device, defaulting to front color");
00242 return GL_OUTPUT_COLOR1_EXT;
00243 break;
00244 case CVPOperand::OFogCoord: return GL_OUTPUT_FOG_EXT;
00245 case CVPOperand::OPointSize: nlstop; return 0;
00246 case CVPOperand::OTex0: return GL_OUTPUT_TEXTURE_COORD0_EXT;
00247 case CVPOperand::OTex1: return GL_OUTPUT_TEXTURE_COORD1_EXT;
00248 case CVPOperand::OTex2: return GL_OUTPUT_TEXTURE_COORD2_EXT;
00249 case CVPOperand::OTex3: return GL_OUTPUT_TEXTURE_COORD3_EXT;
00250 case CVPOperand::OTex4: return GL_OUTPUT_TEXTURE_COORD4_EXT;
00251 case CVPOperand::OTex5: return GL_OUTPUT_TEXTURE_COORD5_EXT;
00252 case CVPOperand::OTex6: return GL_OUTPUT_TEXTURE_COORD6_EXT;
00253 case CVPOperand::OTex7: return GL_OUTPUT_TEXTURE_COORD7_EXT;
00254 default:
00255 nlstop;
00256 break;
00257 }
00258 return 0;
00259 }
00260
00261
00264 static uint convInputRegisterToVBFlag(uint index)
00265 {
00266 switch (index)
00267 {
00268 case CVPOperand::IPosition: return CVertexBuffer::PositionFlag;
00269 case CVPOperand::IWeight: return CVertexBuffer::WeightFlag;
00270 case CVPOperand::INormal: return CVertexBuffer::NormalFlag;
00271 case CVPOperand::IPrimaryColor: return CVertexBuffer::PrimaryColorFlag;
00272 case CVPOperand::ISecondaryColor: return CVertexBuffer::SecondaryColorFlag;
00273 case CVPOperand::IFogCoord: return CVertexBuffer::FogFlag;
00274 case CVPOperand::IPaletteSkin: return CVertexBuffer::PaletteSkinFlag;
00275 case CVPOperand::IEmpty: nlassert(0); break;
00276 case CVPOperand::ITex0:
00277 case CVPOperand::ITex1:
00278 case CVPOperand::ITex2:
00279 case CVPOperand::ITex3:
00280 case CVPOperand::ITex4:
00281 case CVPOperand::ITex5:
00282 case CVPOperand::ITex6:
00283 case CVPOperand::ITex7:
00284 case CVPOperand::ITex8:
00285 return CVertexBuffer::TexCoord0Flag << (index - CVPOperand::ITex0);
00286 default:
00287 nlassert(0);
00288 break;
00289 }
00290 return 0;
00291 }
00292
00293
00294
00295
00296 #define DEBUG_SETUP_EXT_VERTEX_SHADER
00297
00298 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
00299 #define EVS_INFO(what) nlinfo(what)
00300 #else
00301 #define EVS_INFO(what)
00302 #endif
00303
00304
00305
00306 static void doSwizzle(GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW)
00307 {
00308 nglSwizzleEXT(res, in, outX, outY, outZ, outW);
00309 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
00310 std::string swzStr = "Swizzle : ";
00311 GLenum swz[] = { outX, outY, outZ, outW };
00312 for(uint k = 0; k < 4; ++k)
00313 {
00314 switch(swz[k])
00315 {
00316 case GL_X_EXT:
00317 swzStr +=" X";
00318 break;
00319 case GL_NEGATIVE_X_EXT:
00320 swzStr +=" -X";
00321 break;
00322 case GL_Y_EXT:
00323 swzStr +=" Y";
00324 break;
00325 case GL_NEGATIVE_Y_EXT:
00326 swzStr +=" -Y";
00327 break;
00328 break;
00329 case GL_Z_EXT:
00330 swzStr +=" Z";
00331 break;
00332 case GL_NEGATIVE_Z_EXT:
00333 swzStr +=" -Z";
00334 break;
00335 case GL_W_EXT:
00336 swzStr +=" W";
00337 break;
00338 case GL_NEGATIVE_W_EXT:
00339 swzStr +=" -W";
00340 break;
00341 case GL_ZERO_EXT:
00342 swzStr +="0";
00343 break;
00344 case GL_ONE_EXT:
00345 swzStr +="1";
00346 break;
00347 }
00348 }
00349 EVS_INFO(swzStr.c_str());
00350 #endif
00351
00352 }
00353
00354
00355 static void doWriteMask(GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW)
00356 {
00357 nglWriteMaskEXT(res, in, outX, outY, outZ, outW);
00358 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
00359 nlinfo("Write Mask : %c%c%c%c",
00360 outX ? 'x' : '-',
00361 outY ? 'y' : '-',
00362 outZ ? 'z' : '-',
00363 outW ? 'w' : '-'
00364 );
00365 #endif
00366 }
00367
00368
00371 bool CDriverGL::setupEXTVertexShader(const CVPParser::TProgram &program, GLuint id, uint variants[EVSNumVariants], uint16 &usedInputRegisters)
00372 {
00373
00374 uint numOp = 0;
00375 uint numOpIndex = 0;
00376 uint numSwizzle = 0;
00377 uint numEC = 0;
00378 uint numIC = 0;
00379 uint numWM = 0;
00380
00381
00382 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
00383 nlinfo("**********************************************************");
00384 #endif
00385
00386
00387 GLenum glError = glGetError();
00388
00389
00390 nglBindVertexShaderEXT(id);
00391 nglBeginVertexShaderEXT();
00392 {
00393
00394 GLuint firstRegister = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 12);
00395 GLuint firstTempRegister = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 4);
00396 GLuint firstTempScalar = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 3);
00397 GLuint firstAddressRegister = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
00398
00399
00400 variants[EVSSecondaryColorVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_NORMALIZED_RANGE_EXT, 1);
00401 variants[EVSFogCoordsVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_FULL_RANGE_EXT, 1);
00402 variants[EVSSkinWeightVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_NORMALIZED_RANGE_EXT, 1);
00403 variants[EVSPaletteSkinVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_FULL_RANGE_EXT, 1);
00404
00405
00406 GLuint fogTemp = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
00407
00408
00409
00410 GLuint cteOne = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
00411 GLuint cteZero = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
00412
00413
00414 float oneValue = 1.f;
00415 float zeroValue = 0.f;
00416
00417 nglSetLocalConstantEXT( cteOne, GL_FLOAT, &oneValue);
00418 nglSetLocalConstantEXT( cteZero, GL_FLOAT, &zeroValue);
00419
00420
00421
00422 if (firstRegister == 0)
00423 {
00424 nlwarning("Unable to allocate local registers for EXT_vertex_shader");
00425 return false;
00426 }
00427 if (firstTempRegister == 0)
00428 {
00429 nlwarning("Unable to allocate local temp registers for EXT_vertex_shader");
00430 return false;
00431 }
00432 if (firstTempScalar == 0)
00433 {
00434 nlwarning("Unable to allocate temp scalar registers for EXT_vertex_shader");
00435 return false;
00436 }
00437 if (firstAddressRegister == 0)
00438 {
00439 nlwarning("Unable to allocate address register for EXT_vertex_shader");
00440 return false;
00441 }
00442
00443 uint k;
00444 for(k = 0; k < EVSNumVariants; ++k)
00445 {
00446 if (variants[k] == 0)
00447 {
00448 nlwarning("Unable to allocate variants for EXT_vertex_shader");
00449 return false;
00450 }
00451 }
00452
00453
00454 uint componentWritten[16];
00455 std::fill(componentWritten, componentWritten + 16, 0);
00456
00457
00458 GLuint srcValue[3];
00459
00460 GLuint destValue;
00461 GLuint maskedDestValue;
00462
00463
00464 uint l;
00465
00466 for(k = 0; k < program.size(); ++k)
00467 {
00468
00469 uint numSrc = program[k].getNumUsedSrc();
00470 for(l = 0; l < numSrc; ++l)
00471 {
00472 EVS_INFO(("Build source " + toString(l)).c_str());
00473 const CVPOperand &operand = program[k].getSrc(l);
00474 switch (operand.Type)
00475 {
00476 case CVPOperand::InputRegister:
00477 {
00478 switch(operand.Value.InputRegisterValue)
00479 {
00480 case 0: srcValue[l] = _EVSPositionHandle; EVS_INFO("Src = position"); break;
00481 case 1: srcValue[l] = variants[EVSSkinWeightVariant]; EVS_INFO("Src = skin weight"); break;
00482 case 2: srcValue[l] = _EVSNormalHandle; EVS_INFO("Src = normal"); break;
00483 case 3: srcValue[l] = _EVSColorHandle; EVS_INFO("Src = color 0"); break;
00484 case 4: srcValue[l] = variants[EVSSecondaryColorVariant]; EVS_INFO("Src = color 1"); break;
00485 case 5: srcValue[l] = variants[EVSFogCoordsVariant]; EVS_INFO("Src = fog coord"); break;
00486 case 6: srcValue[l] = variants[EVSPaletteSkinVariant]; EVS_INFO("Src = palette skin"); break;
00487 case 7: nlstop;
00488 case 8:
00489 case 9:
00490 case 10:
00491 case 11:
00492 case 12:
00493 case 13:
00494 case 14:
00495 case 15:
00496 {
00497 EVS_INFO(("Src = Tex" + toString(operand.Value.InputRegisterValue - 8)).c_str());
00498 srcValue[l] = _EVSTexHandle[operand.Value.InputRegisterValue - 8];
00499 if (srcValue[l] == 0)
00500 {
00501 nlwarning("Trying to read an unaccessible texture coords for the device when using EXT_vertex_shader, shader loading failed");
00502 return false;
00503 }
00504 }
00505 break;
00506 default:
00507 nlstop;
00508 break;
00509 }
00510 }
00511 break;
00512 case CVPOperand::Constant:
00513 srcValue[l] = _EVSConstantHandle + operand.Value.ConstantValue;
00514 EVS_INFO(("Src = constant" + toString(operand.Value.ConstantValue)).c_str());
00515 break;
00516 case CVPOperand::Variable:
00517 srcValue[l] = firstRegister + operand.Value.VariableValue;
00518 EVS_INFO(("Src = variable register" + toString(operand.Value.VariableValue)).c_str());
00519 break;
00520 default:
00521 nlassert(0);
00522 break;
00523 }
00524
00525 if (operand.Type == CVPOperand::Constant && operand.Indexed)
00526 {
00527 nglShaderOp2EXT(GL_OP_INDEX_EXT, firstTempRegister + 3, firstAddressRegister, srcValue[l]);
00528 EVS_INFO("GL_OP_INDEX_EXT");
00529 ++ numOpIndex;
00530 srcValue[l] = firstTempRegister + 3;
00531 glError = glGetError();
00532 nlassert(glError == GL_NO_ERROR)
00533 }
00534
00535
00536 if (!operand.Swizzle.isIdentity() || operand.Negate)
00537 {
00538
00539 if (!
00540 (
00541 (program[k].Opcode == CVPInstruction::RSQ
00542 || program[k].Opcode == CVPInstruction::RCP
00543 || program[k].Opcode == CVPInstruction::LOG
00544 || program[k].Opcode == CVPInstruction::EXPP
00545 )
00546 &&
00547 !operand.Negate
00548 )
00549 )
00550 {
00551
00552 doSwizzle(firstTempRegister + l, srcValue[l],
00553 convSwizzleToGLFormat(operand.Swizzle.Comp[0], operand.Negate),
00554 convSwizzleToGLFormat(operand.Swizzle.Comp[1], operand.Negate),
00555 convSwizzleToGLFormat(operand.Swizzle.Comp[2], operand.Negate),
00556 convSwizzleToGLFormat(operand.Swizzle.Comp[3], operand.Negate));
00557 ++numSwizzle;
00558 srcValue[l] = firstTempRegister + l;
00559 glError = glGetError();
00560 nlassert(glError == GL_NO_ERROR)
00561 }
00562 }
00563 }
00564
00565
00566 const CVPOperand &destOperand = program[k].Dest;
00567 switch(destOperand.Type)
00568 {
00569 case CVPOperand::Variable:
00570 destValue = firstRegister + destOperand.Value.VariableValue;
00571 break;
00572 case CVPOperand::OutputRegister:
00573 if (destOperand.Value.OutputRegisterValue != CVPOperand::OFogCoord)
00574 {
00575 destValue = convOutputRegisterToEXTVertexShader(destOperand.Value.OutputRegisterValue);
00576 }
00577 else
00578 {
00579 destValue = fogTemp;
00580 }
00581 break;
00582 case CVPOperand::AddressRegister:
00583 destValue = firstAddressRegister;
00584 break;
00585 default:
00586 nlassert(0);
00587 break;
00588 }
00589
00590 uint writeMask = program[k].Dest.WriteMask;
00591 CVPInstruction::EOpcode opcode = program[k].Opcode;
00592 uint outputRegisterIndex = destOperand.Value.OutputRegisterValue;
00593 nlassert(outputRegisterIndex < 16);
00594
00595
00596
00597 bool outputWritten = false;
00598
00599
00600 if (writeMask != 0x0f)
00601 {
00605 if (!(destOperand.Type == CVPOperand::OutputRegister && destValue == fogTemp))
00606 {
00607
00608 if (opcode == CVPInstruction::LOG
00609 || opcode == CVPInstruction::EXPP
00610 || opcode == CVPInstruction::LIT
00611 || opcode == CVPInstruction::RSQ
00612 || opcode == CVPInstruction::RCP
00613 )
00614 {
00615 outputWritten = true;
00616 }
00617 else
00618 {
00619 maskedDestValue = destValue;
00620
00621 destValue = firstTempRegister;
00622 }
00623 }
00624 else
00625 {
00626 componentWritten[outputRegisterIndex] = 0xf;
00627 }
00628 }
00629 else
00630 {
00631 if (destOperand.Type == CVPOperand::OutputRegister)
00632 {
00633 componentWritten[outputRegisterIndex] = 0xf;
00634 }
00635 }
00636
00637
00638 switch (opcode)
00639 {
00640 case CVPInstruction::ARL:
00641 {
00642 nlassert(program[k].Src1.Swizzle.isScalar());
00643 GLuint index = program[k].Src1.Swizzle.Comp[0];
00644 nglExtractComponentEXT(firstAddressRegister, srcValue[0], index);
00645 EVS_INFO("Extract component");
00646 ++numEC;
00647 }
00648 break;
00649 case CVPInstruction::MOV:
00650 {
00651 nglShaderOp1EXT(GL_OP_MOV_EXT, destValue, srcValue[0]);
00652 EVS_INFO("GL_OP_MOV_EXT");
00653 ++numOp;
00654 }
00655 break;
00656 case CVPInstruction::MUL:
00657 nglShaderOp2EXT(GL_OP_MUL_EXT, destValue, srcValue[0], srcValue[1]);
00658 EVS_INFO("GL_OP_MUL_EXT");
00659 ++numOp;
00660 break;
00661 case CVPInstruction::ADD:
00662 nglShaderOp2EXT(GL_OP_ADD_EXT, destValue, srcValue[0], srcValue[1]);
00663 EVS_INFO("GL_OP_ADD_EXT");
00664 ++numOp;
00665 break;
00666 case CVPInstruction::MAD:
00667 nglShaderOp3EXT(GL_OP_MADD_EXT, destValue, srcValue[0], srcValue[1], srcValue[2]);
00668 EVS_INFO("GL_OP_MADD_EXT");
00669 ++numOp;
00670 break;
00671 case CVPInstruction::RSQ:
00672 {
00673 nlassert(program[k].Src1.Swizzle.isScalar());
00674
00675 GLuint index = program[k].Src1.Swizzle.Comp[0];
00676 nglExtractComponentEXT(firstTempScalar, srcValue[0], index);
00677 EVS_INFO("Extract component");
00678 ++numEC;
00679 nglShaderOp1EXT(GL_OP_RECIP_SQRT_EXT, firstTempScalar + 1, firstTempScalar);
00680 EVS_INFO("GL_OP_RECIP_SQRT_EXT");
00681 ++numOp;
00682
00683 for(uint l = 0; l < 4; ++l)
00684 {
00685 if (writeMask & (1 << l))
00686 {
00687 nglInsertComponentEXT(destValue, firstTempScalar + 1, l);
00688 EVS_INFO("Insert component");
00689 nlassert(glGetError() == GL_NO_ERROR);
00690 }
00691 }
00692 }
00693 break;
00694 case CVPInstruction::DP3:
00695 nglShaderOp2EXT(GL_OP_DOT3_EXT, destValue, srcValue[0], srcValue[1]);
00696 EVS_INFO("GL_OP_DOT3_EXT");
00697 ++numOp;
00698 break;
00699 case CVPInstruction::DP4:
00700 nglShaderOp2EXT(GL_OP_DOT4_EXT, destValue, srcValue[0], srcValue[1]);
00701 EVS_INFO("GL_OP_DOT4_EXT");
00702 ++numOp;
00703 break;
00704 case CVPInstruction::DST:
00705 doSwizzle(firstTempRegister, srcValue[0], GL_ONE_EXT, GL_Y_EXT, GL_Z_EXT, GL_ONE_EXT);
00706 EVS_INFO("GL_OP_DOT4_EXT");
00707 ++numOp;
00708 doSwizzle(firstTempRegister + 1, srcValue[1], GL_ONE_EXT, GL_Y_EXT, GL_ONE_EXT, GL_W_EXT);
00709 ++numSwizzle;
00710 nglShaderOp2EXT(GL_OP_MUL_EXT, destValue, firstTempRegister, firstTempRegister + 1);
00711 EVS_INFO("GL_OP_MUL_EXT");
00712 ++numOp;
00713 break;
00714 case CVPInstruction::LIT:
00715 {
00716 uint writeMask = program[k].Dest.WriteMask;
00717 nglExtractComponentEXT(firstTempScalar, srcValue[0], 0);
00718 if (writeMask & 4)
00719 {
00720 nglExtractComponentEXT(firstTempScalar + 1, srcValue[0], 1);
00721 EVS_INFO("Extract component");
00722 ++numEC;
00723 nglExtractComponentEXT(firstTempScalar + 2, srcValue[0], 3);
00724 EVS_INFO("Extract component");
00725 ++numEC;
00726
00727 nglShaderOp2EXT(GL_OP_POWER_EXT, firstTempScalar + 2, firstTempScalar + 1, firstTempScalar + 2);
00728 EVS_INFO("GL_OP_POWER_EXT");
00729 ++numOp;
00730 nglShaderOp2EXT(GL_OP_SET_GE_EXT, firstTempScalar + 1, firstTempScalar, cteZero);
00731 EVS_INFO("GL_OP_SET_GE_EXT");
00732 ++numOp;
00733 nglShaderOp2EXT(GL_OP_MUL_EXT, firstTempScalar + 2, firstTempScalar + 2, firstTempScalar + 1);
00734 EVS_INFO("GL_OP_MUL_EXT");
00735 ++numOp;
00736
00737 nglInsertComponentEXT(destValue, firstTempScalar + 2, 2);
00738 EVS_INFO("Insert component");
00739 ++numIC;
00740 }
00741 if (writeMask & 2)
00742 {
00743
00744 nglShaderOp3EXT(GL_OP_CLAMP_EXT, firstTempScalar, firstTempScalar, cteZero, cteOne);
00745 EVS_INFO("GL_OP_CLAMP_EXT");
00746 ++numOp;
00747 nglInsertComponentEXT(destValue, firstTempScalar, 1);
00748 EVS_INFO("Insert component");
00749 ++numIC;
00750 }
00751
00752 if (writeMask & (1 + 8))
00753 {
00754 doSwizzle(destValue, destValue,
00755 (writeMask & 1) ? GL_ONE_EXT : GL_X_EXT,
00756 GL_Y_EXT,
00757 GL_Z_EXT,
00758 (writeMask & 8) ? GL_ONE_EXT : GL_W_EXT);
00759 ++numSwizzle;
00760 }
00761
00762 }
00763 break;
00764 case CVPInstruction::MIN:
00765 nglShaderOp2EXT(GL_OP_MIN_EXT, destValue, srcValue[0], srcValue[1]);
00766 EVS_INFO("GL_OP_MIN_EXT");
00767 ++numOp;
00768 break;
00769 case CVPInstruction::MAX:
00770 nglShaderOp2EXT(GL_OP_MAX_EXT, destValue, srcValue[0], srcValue[1]);
00771 EVS_INFO("GL_OP_MAX_EXT");
00772 ++numOp;
00773 break;
00774 case CVPInstruction::SLT:
00775 nglShaderOp2EXT(GL_OP_SET_LT_EXT, destValue, srcValue[0], srcValue[1]);
00776 EVS_INFO("GL_OP_SET_LT_EXT");
00777 ++numOp;
00778 break;
00779 case CVPInstruction::SGE:
00780 nglShaderOp2EXT(GL_OP_SET_GE_EXT, destValue, srcValue[0], srcValue[1]);
00781 EVS_INFO("GL_OP_SET_GE_EXT");
00782 ++numOp;
00783 break;
00784 case CVPInstruction::EXPP:
00785 {
00786 uint writeMask = program[k].Dest.WriteMask;
00787 nlassert(program[k].Src1.Swizzle.isScalar());
00788 GLuint compIndex = program[k].Src1.Swizzle.Comp[0];
00789 nglExtractComponentEXT(firstTempScalar + 2, srcValue[0], compIndex);
00790 EVS_INFO("Extract component");
00791 ++numEC;
00792 if (writeMask & 1)
00793 {
00794 nglShaderOp1EXT(GL_OP_FLOOR_EXT, firstTempScalar, firstTempScalar + 2);
00795 EVS_INFO("GL_OP_FLOOR_EXT");
00796 ++numOp;
00797 nglShaderOp1EXT(GL_OP_EXP_BASE_2_EXT, firstTempScalar, firstTempScalar);
00798 EVS_INFO("GL_OP_EXP_BASE_2_EXT");
00799 ++numOp;
00800 }
00801 if (writeMask & 2)
00802 {
00803 nglShaderOp1EXT(GL_OP_FRAC_EXT, firstTempScalar + 1, firstTempScalar + 2);
00804 EVS_INFO("GL_OP_FRAC_EXT");
00805 ++numOp;
00806 }
00807 if (writeMask & 4) nglShaderOp1EXT(GL_OP_EXP_BASE_2_EXT, firstTempScalar + 2, firstTempScalar + 2);
00808
00809 if (writeMask & 1) { nglInsertComponentEXT(destValue, firstTempScalar, 0); EVS_INFO("Insert component"); ++numIC; }
00810 if (writeMask & 2) { nglInsertComponentEXT(destValue, firstTempScalar + 1, 1); EVS_INFO("Insert component"); ++numIC; }
00811 if (writeMask & 4) { nglInsertComponentEXT(destValue, firstTempScalar + 2, 2); EVS_INFO("Insert component"); ++numIC; }
00812
00813 if (writeMask & 8) { doSwizzle(destValue, destValue, GL_X_EXT, GL_Y_EXT, GL_Z_EXT, GL_ONE_EXT); ++numSwizzle; }
00814 }
00815 break;
00816 case CVPInstruction::LOG:
00817 {
00818 uint writeMask = program[k].Dest.WriteMask;
00819 nlassert(program[k].Src1.Swizzle.isScalar());
00820
00821 nglExtractComponentEXT(firstTempScalar, srcValue[0], (GLuint) program[k].Src1.Swizzle.Comp[0]);
00822 EVS_INFO("Extract component");
00823 ++numEC;
00824
00825 nglShaderOp1EXT(GL_OP_NEGATE_EXT, firstTempScalar + 1, firstTempScalar);
00826 EVS_INFO("GL_OP_NEGATE_EXT");
00827 ++numOp;
00828 nglShaderOp2EXT(GL_OP_MAX_EXT, firstTempScalar, firstTempScalar, firstTempScalar + 1);
00829 EVS_INFO("GL_OP_MAX_EXT");
00830 ++numOp;
00831 nglShaderOp1EXT(GL_OP_LOG_BASE_2_EXT, firstTempScalar, firstTempScalar);
00832 EVS_INFO("GL_OP_LOG_BASE_2_EXT");
00833 ++numOp;
00834
00835 for(uint l = 0; l < 4; ++l)
00836 {
00837 if (writeMask & (1 << l))
00838 {
00839 nglInsertComponentEXT(destValue, firstTempScalar, l);
00840 EVS_INFO("Insert component");
00841 nlassert(glGetError() == GL_NO_ERROR);
00842 }
00843 }
00844 }
00845 break;
00846 case CVPInstruction::RCP:
00847 {
00848 uint writeMask = program[k].Dest.WriteMask;
00849 nlassert(program[k].Src1.Swizzle.isScalar());
00850
00851 nglExtractComponentEXT(firstTempScalar, srcValue[0], (GLuint) program[k].Src1.Swizzle.Comp[0]);
00852 EVS_INFO("Extract component");
00853 ++numEC;
00854 nglShaderOp1EXT(GL_OP_RECIP_EXT, firstTempScalar + 1, firstTempScalar);
00855 EVS_INFO("GL_OP_RECIP_EXT");
00856 ++numOp;
00857
00858 for(uint l = 0; l < 4; ++l)
00859 {
00860 if (writeMask & (1 << l))
00861 {
00862 nglInsertComponentEXT(destValue, firstTempScalar + 1, l);
00863 EVS_INFO("insert component");
00864 ++numIC;
00865 }
00866 }
00867 }
00868 break;
00869 }
00870
00871 glError = glGetError();
00872 nlassert(glError == GL_NO_ERROR)
00873
00874
00875
00876 if (writeMask != 0x0f)
00877 {
00878 if (destOperand.Type == CVPOperand::OutputRegister && destValue != fogTemp)
00879 {
00880 uint &outputMask = componentWritten[outputRegisterIndex];
00881
00882 if ((maskedDestValue >= GL_OUTPUT_TEXTURE_COORD0_EXT && maskedDestValue <= GL_OUTPUT_TEXTURE_COORD7_EXT)
00883 || maskedDestValue == GL_OUTPUT_COLOR0_EXT
00884 || maskedDestValue == GL_OUTPUT_COLOR1_EXT
00885 )
00886 {
00887
00888 bool found = false;
00889
00890
00891 for(uint m = k + 1; m < program.size(); ++m)
00892 {
00893 if (program[m].Dest.Type == CVPOperand::OutputRegister)
00894 {
00895 if (program[m].Dest.Value.OutputRegisterValue == program[k].Dest.Value.OutputRegisterValue)
00896 {
00897 found = true;
00898 break;
00899 }
00900 }
00901 }
00902
00903 if (found)
00904 {
00905 if (!outputWritten)
00906 {
00907
00908 doWriteMask(maskedDestValue, destValue,
00909 writeMask & 1 ? GL_TRUE : GL_FALSE,
00910 writeMask & 2 ? GL_TRUE : GL_FALSE,
00911 writeMask & 4 ? GL_TRUE : GL_FALSE,
00912 writeMask & 8 ? GL_TRUE : GL_FALSE);
00913 ++numWM;
00914 }
00915 }
00916 else
00917 {
00918 if ((outputMask | writeMask) == 0xf)
00919 {
00920 if (!outputWritten)
00921 {
00922
00923
00924 doWriteMask(maskedDestValue, destValue,
00925 writeMask & 1 ? GL_TRUE : GL_FALSE,
00926 writeMask & 2 ? GL_TRUE : GL_FALSE,
00927 writeMask & 4 ? GL_TRUE : GL_FALSE,
00928 writeMask & 8 ? GL_TRUE : GL_FALSE);
00929 ++numWM;
00930 }
00931 }
00932 else
00933 {
00934 uint prevMask = outputMask;
00935 uint newMask = writeMask | outputMask;
00936
00937
00938
00939
00940 if (maskedDestValue == GL_OUTPUT_COLOR0_EXT)
00941 {
00942 doSwizzle(firstTempRegister, destValue,
00943 newMask & 1 ? GL_X_EXT : GL_ONE_EXT,
00944 newMask & 2 ? GL_Y_EXT : GL_ONE_EXT,
00945 newMask & 4 ? GL_Z_EXT : GL_ONE_EXT,
00946 newMask & 8 ? GL_W_EXT : GL_ONE_EXT);
00947 }
00948 else
00949 {
00950 doSwizzle(firstTempRegister, destValue,
00951 newMask & 1 ? GL_X_EXT : GL_ZERO_EXT,
00952 newMask & 2 ? GL_Y_EXT : GL_ZERO_EXT,
00953 newMask & 4 ? GL_Z_EXT : GL_ZERO_EXT,
00954 newMask & 8 ? GL_W_EXT : GL_ONE_EXT);
00955 }
00956 if (!outputWritten)
00957 {
00958 ++numWM;
00959 doWriteMask(maskedDestValue, firstTempRegister,
00960 prevMask & 1 ? GL_FALSE : GL_TRUE,
00961 prevMask & 2 ? GL_FALSE : GL_TRUE,
00962 prevMask & 4 ? GL_FALSE : GL_TRUE,
00963 prevMask & 8 ? GL_FALSE : GL_TRUE
00964 );
00965 ++numWM;
00966 }
00967 outputMask = 0xf;
00968 }
00969 }
00970 }
00971 else
00972 {
00973 if (!outputWritten)
00974 {
00975 doWriteMask(maskedDestValue, destValue,
00976 writeMask & 1 ? GL_TRUE : GL_FALSE,
00977 writeMask & 2 ? GL_TRUE : GL_FALSE,
00978 writeMask & 4 ? GL_TRUE : GL_FALSE,
00979 writeMask & 8 ? GL_TRUE : GL_FALSE);
00980 ++numWM;
00981 }
00982 }
00983
00984 outputMask |= writeMask;
00985 }
00986 else if (destOperand.Type != CVPOperand::OutputRegister)
00987 {
00988 if (!outputWritten)
00989 {
00990 doWriteMask(maskedDestValue, destValue,
00991 writeMask & 1 ? GL_TRUE : GL_FALSE,
00992 writeMask & 2 ? GL_TRUE : GL_FALSE,
00993 writeMask & 4 ? GL_TRUE : GL_FALSE,
00994 writeMask & 8 ? GL_TRUE : GL_FALSE);
00995 ++numWM;
00996 }
00997 }
00998 }
00999
01000 glError = glGetError();
01001 nlassert(glError == GL_NO_ERROR)
01002 }
01003
01004
01005
01006
01007 if (componentWritten[CVPOperand::OPrimaryColor] == 0)
01008 {
01009
01010 doSwizzle(GL_OUTPUT_COLOR0_EXT, _EVSPositionHandle, GL_ONE_EXT, GL_ONE_EXT, GL_ONE_EXT, GL_ONE_EXT);
01011 EVS_INFO("Swizzle (Complete primary color)");
01012 ++numSwizzle;
01013 }
01014 else
01015 {
01016 nlassert(componentWritten[CVPOperand::OPrimaryColor] == 0xf)
01017 }
01018 if (componentWritten[CVPOperand::OSecondaryColor] == 0)
01019 {
01020
01021 doSwizzle(GL_OUTPUT_COLOR1_EXT, _EVSPositionHandle, GL_ZERO_EXT, GL_ZERO_EXT, GL_ZERO_EXT, GL_ONE_EXT);
01022 EVS_INFO("Swizzle (Complete secondary color)");
01023 ++numSwizzle;
01024 }
01025 else
01026 {
01027 nlassert(componentWritten[CVPOperand::OSecondaryColor] == 0xf)
01028 }
01029 nlassert(componentWritten[CVPOperand::OHPosition] == 0xf);
01030
01031 glError = glGetError();
01032 nlassert(glError == GL_NO_ERROR);
01033
01034
01035 if (componentWritten[CVPOperand::OFogCoord] == 0xf)
01036 {
01037
01038 doSwizzle(firstTempRegister, _EVSConstantHandle + 96, GL_X_EXT, GL_X_EXT, GL_X_EXT, GL_X_EXT);
01039 doSwizzle(firstTempRegister + 1, _EVSConstantHandle + 96, GL_Y_EXT, GL_Y_EXT, GL_Y_EXT, GL_Y_EXT);
01040 nglShaderOp3EXT(GL_OP_MADD_EXT, firstTempRegister + 2, fogTemp, firstTempRegister, firstTempRegister + 1);
01041 EVS_INFO("Use MAD for fog conversion");
01042 nglExtractComponentEXT(GL_OUTPUT_FOG_EXT, firstTempRegister + 2, 0);
01043 EVS_INFO("Extract component to fog");
01044 }
01045
01046 glError = glGetError();
01047 nlassert(glError == GL_NO_ERROR);
01048 }
01049 nglEndVertexShaderEXT();
01050
01051 glError = glGetError();
01052 nlassert(glError == GL_NO_ERROR);
01053
01054 GLboolean optimizedShader;
01055 glGetBooleanv(GL_VERTEX_SHADER_OPTIMIZED_EXT, &optimizedShader);
01056 if (!optimizedShader)
01057 {
01058 nlwarning("Failed to optimize a vertex program with the EXT_vertex_shader extension, this shader will be disabled");
01059 return false;
01060 }
01061
01062
01063 usedInputRegisters = 0;
01064
01065 uint k, l;
01066
01067 for(k = 0; k < program.size(); ++k)
01068 {
01069 uint numSrc = program[k].getNumUsedSrc();
01070 for(l = 0; l < numSrc; ++l)
01071 {
01072 const CVPOperand &op = program[k].getSrc(l);
01073 if (op.Type == CVPOperand::InputRegister)
01074 {
01075 usedInputRegisters |= convInputRegisterToVBFlag(op.Value.InputRegisterValue);
01076 }
01077 }
01078 }
01079
01080 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
01081 nlinfo("========================");
01082 nlinfo("num Opcode = %d", numOp);
01083 nlinfo("num Indexing = %d", numOpIndex);
01084 nlinfo("num Swizzle = %d", numSwizzle);
01085 nlinfo("num extract component = %d", numEC);
01086 nlinfo("num insert component = %d", numIC);
01087 nlinfo("num write mask = %d", numWM);
01088 #endif
01089
01090 return true;
01091
01092 }
01093
01094
01095 bool CDriverGL::activeEXTVertexShader (CVertexProgram *program)
01096 {
01097
01098 if (program)
01099 {
01100
01101 CVertexProgamDrvInfosGL *drvInfo;
01102
01103
01104 if (program->_DrvInfo==NULL)
01105 {
01106
01107 CVPParser parser;
01108 CVPParser::TProgram parsedProgram;
01109 std::string errorOutput;
01110 bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
01111 if (!result)
01112 {
01113 nlwarning("Unable to parse a vertex program.");
01114 #ifdef NL_DEBUG
01115 nlerror(errorOutput.c_str());
01116 #endif
01117 return false;
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 ItVtxPrgDrvInfoPtrList it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end());
01133
01134
01135 *it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
01136
01137 program->_DrvInfo=drvInfo;
01138
01139 if (!setupEXTVertexShader(parsedProgram, drvInfo->ID, drvInfo->Variants, drvInfo->UsedVertexComponents))
01140 {
01141 delete drvInfo;
01142 program->_DrvInfo = NULL;
01143 _VtxPrgDrvInfos.erase(it);
01144 return false;
01145 }
01146 }
01147 else
01148 {
01149
01150 drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
01151 }
01152
01153 glEnable( GL_VERTEX_SHADER_EXT);
01154 _VertexProgramEnabled = true;
01155 nglBindVertexShaderEXT( drvInfo->ID );
01156 _LastSetuppedVP = program;
01157 }
01158 else
01159 {
01160 glDisable( GL_VERTEX_SHADER_EXT );
01161 _VertexProgramEnabled = false;
01162 }
01163 return true;
01164 }
01165
01166
01167 bool CDriverGL::activeVertexProgram (CVertexProgram *program)
01168 {
01169
01170 if (_Extensions.NVVertexProgram)
01171 {
01172 return activeNVVertexProgram(program);
01173 }
01174 else if (_Extensions.EXTVertexShader)
01175 {
01176 return activeEXTVertexShader(program);
01177 }
01178
01179
01180 return false;
01181 }
01182
01183
01184
01185
01186 void CDriverGL::setConstant (uint index, float f0, float f1, float f2, float f3)
01187 {
01188
01189 if (_Extensions.NVVertexProgram)
01190 {
01191
01192 nglProgramParameter4fNV (GL_VERTEX_PROGRAM_NV, index, f0, f1, f2, f3);
01193 }
01194 else if (_Extensions.EXTVertexShader)
01195 {
01196 float datas[] = { f0, f1, f2, f3 };
01197 nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
01198 }
01199 }
01200
01201
01202
01203
01204 void CDriverGL::setConstant (uint index, double d0, double d1, double d2, double d3)
01205 {
01206
01207 if (_Extensions.NVVertexProgram)
01208 {
01209
01210 nglProgramParameter4dNV (GL_VERTEX_PROGRAM_NV, index, d0, d1, d2, d3);
01211 }
01212 else if (_Extensions.EXTVertexShader)
01213 {
01214 double datas[] = { d0, d1, d2, d3 };
01215 nglSetInvariantEXT(_EVSConstantHandle + index, GL_DOUBLE, datas);
01216 }
01217 }
01218
01219
01220
01221
01222 void CDriverGL::setConstant (uint index, const NLMISC::CVector& value)
01223 {
01224
01225 if (_Extensions.NVVertexProgram)
01226 {
01227
01228 nglProgramParameter4fNV (GL_VERTEX_PROGRAM_NV, index, value.x, value.y, value.z, 0);
01229 }
01230 else if (_Extensions.EXTVertexShader)
01231 {
01232 float datas[] = { value.x, value.y, value.z, 0 };
01233 nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
01234 }
01235 }
01236
01237
01238
01239
01240 void CDriverGL::setConstant (uint index, const NLMISC::CVectorD& value)
01241 {
01242
01243 if (_Extensions.NVVertexProgram)
01244 {
01245
01246 nglProgramParameter4dNV (GL_VERTEX_PROGRAM_NV, index, value.x, value.y, value.z, 0);
01247 }
01248 else if (_Extensions.EXTVertexShader)
01249 {
01250 double datas[] = { value.x, value.y, value.z, 0 };
01251 nglSetInvariantEXT(_EVSConstantHandle + index, GL_DOUBLE, datas);
01252 }
01253 }
01254
01255
01256
01257 void CDriverGL::setConstant (uint index, uint num, const float *src)
01258 {
01259
01260 if (_Extensions.NVVertexProgram)
01261 {
01262 nglProgramParameters4fvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
01263 }
01264 else if (_Extensions.EXTVertexShader)
01265 {
01266 for(uint k = 0; k < num; ++k)
01267 {
01268 nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_FLOAT, (void *) (src + 4 * k));
01269 }
01270 }
01271 }
01272
01273
01274 void CDriverGL::setConstant (uint index, uint num, const double *src)
01275 {
01276
01277 if (_Extensions.NVVertexProgram)
01278 {
01279 nglProgramParameters4dvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
01280 }
01281 else if (_Extensions.EXTVertexShader)
01282 {
01283 for(uint k = 0; k < num; ++k)
01284 {
01285 nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_DOUBLE, (void *) (src + 4 * k));
01286 }
01287 }
01288 }
01289
01290
01291
01292 const uint CDriverGL::GLMatrix[IDriver::NumMatrix]=
01293 {
01294 GL_MODELVIEW,
01295 GL_PROJECTION,
01296 GL_MODELVIEW_PROJECTION_NV
01297 };
01298
01299
01300
01301
01302 const uint CDriverGL::GLTransform[IDriver::NumTransform]=
01303 {
01304 GL_IDENTITY_NV,
01305 GL_INVERSE_NV,
01306 GL_TRANSPOSE_NV,
01307 GL_INVERSE_TRANSPOSE_NV
01308 };
01309
01310
01311
01312
01313 void CDriverGL::setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
01314 {
01315
01316 if (_Extensions.NVVertexProgram)
01317 {
01318
01319 refreshRenderSetup();
01320
01321
01322 nglTrackMatrixNV (GL_VERTEX_PROGRAM_NV, index, GLMatrix[matrix], GLTransform[transform]);
01323
01324 nglTrackMatrixNV (GL_VERTEX_PROGRAM_NV, index, GL_NONE, GL_IDENTITY_NV);
01325 }
01326 else if (_Extensions.EXTVertexShader)
01327 {
01328
01329 refreshRenderSetup();
01330 CMatrix mat;
01331 switch (matrix)
01332 {
01333 case IDriver::ModelView:
01334 mat = _ModelViewMatrix;
01335 break;
01336 case IDriver::Projection:
01337 {
01338 refreshProjMatrixFromGL();
01339 mat = _GLProjMat;
01340 }
01341 break;
01342 case IDriver::ModelViewProjection:
01343 refreshProjMatrixFromGL();
01344 mat = _GLProjMat * _ModelViewMatrix;
01345 break;
01346 }
01347
01348 switch(transform)
01349 {
01350 case IDriver::Identity: break;
01351 case IDriver::Inverse:
01352 mat.invert();
01353 break;
01354 case IDriver::Transpose:
01355 mat.transpose();
01356 break;
01357 case IDriver::InverseTranspose:
01358 mat.invert();
01359 mat.transpose();
01360 break;
01361 }
01362 mat.transpose();
01363 float matDatas[16];
01364 mat.get(matDatas);
01365 nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, matDatas);
01366 nglSetInvariantEXT(_EVSConstantHandle + index + 1, GL_FLOAT, matDatas + 4);
01367 nglSetInvariantEXT(_EVSConstantHandle + index + 2, GL_FLOAT, matDatas + 8);
01368 nglSetInvariantEXT(_EVSConstantHandle + index + 3, GL_FLOAT, matDatas + 12);
01369 }
01370 }
01371
01372
01373
01374 void CDriverGL::enableVertexProgramDoubleSidedColor(bool doubleSided)
01375 {
01376
01377 if (_Extensions.NVVertexProgram)
01378 {
01379
01380 if(doubleSided)
01381 glEnable (GL_VERTEX_PROGRAM_TWO_SIDE_NV);
01382 else
01383 glDisable (GL_VERTEX_PROGRAM_TWO_SIDE_NV);
01384 }
01385 }
01386
01387
01388
01389 bool CDriverGL::supportVertexProgramDoubleSidedColor() const
01390 {
01391
01392 return _Extensions.NVVertexProgram;
01393 }
01394
01395
01396 }