📄 ps1.0_program.cpp
字号:
#include "ps1.0_program.h"
#include "nvparse_errors.h"
#include "nvparse_externs.h"
#include <OgreGLPrerequisites.h>
#include <string>
#include <map>
#include <algorithm>
#include <string.h>
#include <set>
using namespace std;
using namespace ps10;
struct ltstr
{
bool operator()(const char* s1, const char* s2) const
{
return strcmp(s1, s2) < 0;
}
};
#define DBG_MESG(msg, line) errors.set(msg, line)
//#define DBG_MESG(msg, line)
namespace ps10
{
std::map<int, std::pair<int,int> > constToStageAndConstMap;
std::vector<int> constToStageArray;
std::map<int, int> stageToConstMap; // to keep track of which constants have been used up for this stage.
// r-value of 0 means none, r-value of 1 means c0 used, and r-value of 2 means both used.
//std::map<int, int> constToStageMap;
std::map<int, GLenum> stageToTargetMap;
std::set<const char*, ltstr> alphaBlueRegisters; // Keeps track of whether the result of a register
// was a dp3, if a register is in this set, it means that if it is used a source for the alpha
// component the blue component should be used, and not the alpha component.
void SetFinalCombinerStage();
}
void RemoveFromAlphaBlue(std::string s)
{
std::set<const char*, ltstr>::iterator iter =
ps10::alphaBlueRegisters.find(s.c_str());
if (iter != alphaBlueRegisters.end())
alphaBlueRegisters.erase(iter);
}
/*
void AddToMap(string s, int stage)
{
const char* cstr = s.c_str();
if (cstr[0] == 'c')
{
int constNum = atoi(&cstr[1]);
if (constNum < 0 || constNum > 7)
return;
constToStageMap[constNum] = stage;
}
}
*/
bool AddToMap(string s, int stage, GLenum& constVal)
{
const char* cstr = s.c_str();
if (cstr[0] == 'c')
{
int constNum = atoi(&cstr[1]);
std::map<int, int>::iterator iter = stageToConstMap.find(stage);
if (iter == stageToConstMap.end())
{
// no constants used for this stage.
std::pair<int, int> temp;
temp.first = stage;
temp.second = 0;
constToStageAndConstMap[constNum] = temp;
stageToConstMap[stage] = 0;
constVal = 0;
constToStageArray.push_back(constNum);
constToStageArray.push_back(stage);
constToStageArray.push_back(constVal);
}
else
{
int constUsed = (*iter).second;
if (constUsed >= 1)
return false;
else // const0 has been used, so use const1 for this stage.
{
std::pair<int,int> temp;
temp.first = stage;
temp.second = 1;
constToStageAndConstMap[constNum] = temp;
stageToConstMap[stage] = 1;
constVal = 1;
constToStageArray.push_back(constNum);
constToStageArray.push_back(stage);
constToStageArray.push_back(constVal);
}
}
}
constVal += GL_CONSTANT_COLOR0_NV;
return true;
}
bool IsLegalTarget(int target)
{
if (target == GL_TEXTURE_CUBE_MAP_ARB)
return true;
if (target == GL_TEXTURE_3D)
return true;
#if defined(GL_EXT_texture_rectangle)
if (target == GL_TEXTURE_RECTANGLE_EXT)
return true;
#elif defined(GL_NV_texture_rectangle)
if (target == GL_TEXTURE_RECTANGLE_NV)
return true;
#endif
if (target == GL_TEXTURE_2D)
return true;
if (target == GL_TEXTURE_1D)
return true;
return false;
}
bool ps10_set_map(const std::vector<int>& argv)
{
if (argv.size() % 2 != 0)
{
errors.set("Odd number of arguments for texture target map.");
return false;
}
for (unsigned int i=0;i<argv.size();i=i+2)
{
int stage = argv[i];
int target = argv[i+1];
if (!IsLegalTarget(target))
{
errors.set("Illegal target in texture target map.");
return false;
}
ps10::stageToTargetMap[stage] = target;
}
return true;
}
int const_to_combiner_reg_mapping[32][3]; // each 3 tuple is: (constant#, stage #, reg #)
int const_to_combiner_reg_mapping_count = 0;
namespace
{
struct set_constants
{
void operator() (constdef c)
{
if(c.reg[0] != 'c' && c.reg.size() != 2)
DBG_MESG("def line must use constant registers", 0);
int reg = c.reg[1] - '0';
GLenum stage = GL_COMBINER0_NV + (reg / 2);
GLenum cclr = GL_CONSTANT_COLOR0_NV + (reg % 2);
GLfloat cval[4];
cval[0] = c.r;
cval[1] = c.g;
cval[2] = c.b;
cval[3] = c.a;
glCombinerStageParameterfvNV_ptr(stage, cclr, cval);
}
};
GLenum get_tex_target(int stage)
{
std::map<int, GLenum>::iterator iter = stageToTargetMap.find(stage);
if (iter != stageToTargetMap.end())
return (*iter).second;
// If no mapping set, use the current state. This will not work correctly, in general,
// if nvparse was invoked within a display list.
if(glIsEnabled(GL_TEXTURE_CUBE_MAP_ARB))
return GL_TEXTURE_CUBE_MAP_ARB;
if(glIsEnabled(GL_TEXTURE_3D))
return GL_TEXTURE_3D;
#if defined(GL_EXT_texture_rectangle)
if(glIsEnabled(GL_TEXTURE_RECTANGLE_EXT))
return GL_TEXTURE_RECTANGLE_EXT;
#elif defined(GL_NV_texture_rectangle)
if(glIsEnabled(GL_TEXTURE_RECTANGLE_NV))
return GL_TEXTURE_RECTANGLE_NV;
#endif
if(glIsEnabled(GL_TEXTURE_2D))
return GL_TEXTURE_2D;
if(glIsEnabled(GL_TEXTURE_1D))
return GL_TEXTURE_1D;
//otherwise make the op none...
return GL_NONE;
}
struct set_texture_shaders
{
set_texture_shaders(vector<constdef> * cdef)
{
for(stage = 0; stage < 4; stage++)
{
glActiveTextureARB_ptr(GL_TEXTURE0_ARB + stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
}
stage = 0;
c = cdef;
}
void operator() (vector<string> & instr)
{
if(stage > 3)
return;
glActiveTextureARB_ptr(GL_TEXTURE0_ARB + stage);
string op = instr[0];
if(op == "tex")
{
if(instr.size() != 2)
fprintf(stderr,"incorrect \"tex\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, get_tex_target(stage));
}
else if(op == "texbem")
{
if(instr.size() != 3 || stage == 0)
fprintf(stderr,"incorrect \"texbem\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
if(reg2stage.count(instr[2]) == 0)
fprintf(stderr,"incorrect \"texbem\" instruction, stage %d...\n", stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + reg2stage[instr[2]]);
}
else if(op == "texbeml")
{
if(instr.size() != 3 || stage == 0)
fprintf(stderr,"incorrect \"texbeml\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_SCALE_NV);
if(reg2stage.count(instr[2]) == 0)
fprintf(stderr,"incorrect \"texbeml\" instruction, stage %d...\n", stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + reg2stage[instr[2]]);
}
else if(op == "texcoord")
{
if(instr.size() != 2)
fprintf(stderr,"incorrect \"texcoord\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_PASS_THROUGH_NV);
}
else if(op == "texkill")
{
if(instr.size() != 2)
fprintf(stderr,"incorrect \"texkill\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_CULL_FRAGMENT_NV);
}
else if(op == "texm3x2pad")
{
if(instr.size() != 3 || stage == 0)
fprintf(stderr,"incorrect \"texm3x2pad\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV);
if(instr[2].find("_bx2") != string::npos)
{
instr[2].erase(instr[2].begin() + instr[2].find("_bx2"), instr[2].end());
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL_EXPAND_NORMAL_NV);
}
if(reg2stage.count(instr[2]) == 0)
fprintf(stderr,"incorrect \"texm3x2pad\" instruction, stage %d...\n", stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + reg2stage[instr[2]]);
}
else if(op == "texm3x2tex")
{
if(instr.size() != 3 || stage == 0)
fprintf(stderr,"incorrect \"texm3x2tex\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_2D_NV);
if(instr[2].find("_bx2") != string::npos)
{
instr[2].erase(instr[2].begin() + instr[2].find("_bx2"), instr[2].end());
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL_EXPAND_NORMAL_NV);
}
if(reg2stage.count(instr[2]) == 0)
fprintf(stderr,"incorrect \"texm3x2tex\" instruction, stage %d...\n", stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + reg2stage[instr[2]]);
}
else if(op == "texm3x3pad")
{
if(instr.size() != 3 || stage == 0)
fprintf(stderr,"incorrect \"texm3x3pad\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV);
if(instr[2].find("_bx2") != string::npos)
{
instr[2].erase(instr[2].begin() + instr[2].find("_bx2"), instr[2].end());
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL_EXPAND_NORMAL_NV);
}
if(reg2stage.count(instr[2]) == 0)
fprintf(stderr,"incorrect \"texm3x3pad\" instruction, stage %d...\n", stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + reg2stage[instr[2]]);
}
else if(op == "texm3x3tex")
{
if(instr.size() != 3 || stage == 0)
fprintf(stderr,"incorrect \"texm3x3tex\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV);
if(instr[2].find("_bx2") != string::npos)
{
instr[2].erase(instr[2].begin() + instr[2].find("_bx2"), instr[2].end());
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL_EXPAND_NORMAL_NV);
}
if(reg2stage.count(instr[2]) == 0)
fprintf(stderr,"incorrect \"texm3x3tex\" instruction, stage %d...\n", stage);
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + reg2stage[instr[2]]);
}
else if(op == "texm3x3spec")
{
if(instr.size() != 4 || stage == 0)
fprintf(stderr,"incorrect \"texm3x3spec\" instruction, stage %d...\n", stage);
reg2stage[instr[1]] = stage;
if(! c)
return;
constdef cd;
for(int i = c->size()-1; i >= 0; i--)
{
cd = (*c)[i];
if(cd.reg == "c0")
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -