我在OpenGL / GLSL应用程序中实现了普通的映射着色器。为了计算片段着色器中的凹凸和阴影因子,我需要从顶点着色器发送一些数据,例如切线空间中的光方向和光场中的顶点位置,用于场景的每个光。所以要做的工作我需要声明2输出变量,如下面(顶点着色器):
#define MAX_LIGHT_COUNT 5
[...]
out vec4 ShadowCoords[MAX_LIGHT_COUNT]; //Vertex position in light space
out vec3 lightDir_TS[MAX_LIGHT_COUNT]; //light direction in tangent space
uniform int LightCount;
[...]
for (int idx = 0; idx < LightCount; idx++)
{
[...]
lightDir_TS[idx] = TBN * lightDir_CS;
ShadowCoords[idx] = ShadowInfos[idx].ShadowMatrix * VertexPosition;
[...]
}
在片段着色器中,由于以下输入声明,我恢复了这些变量:
in vec3 lightDir_TS[MAX_LIGHT_COUNT];
in vec4 ShadowCoords[MAX_LIGHT_COUNT];
其余代码对解释我的问题并不重要。
所以现在这里的结果是图像:
你可以看到,直到这里一切都好!
但是现在,为了简单起见,我想使用单个输出声明而不是2!因此,逻辑上的选择是使用如下的输入/输出数据块:
#define MAX_LIGHT_COUNT 5
[...]
out LightData_VS
{
vec3 lightDir_TS;
vec4 ShadowCoords;
} LightData_OUT[MAX_LIGHT_COUNT];
uniform int LightCount;
[...]
for (int idx = 0; idx < LightCount; idx++)
{
[...]
LightData_OUT[idx].lightDir_TS = TBN * lightDir_CS;
LightData_OUT[idx].ShadowCoords = ShadowInfos[idx].ShadowMatrix * VertexPosition;
[...]
}
在片段着色器中输入数据块:
in LightData_VS
{
vec3 lightDir_TS;
vec4 ShadowCoords;
} LightData_IN[MAX_LIGHT_COUNT];
但是这次当我执行我的程序时,我有以下显示:
正如您所看到的,镜面反射光与上面第一种情况不同!
但是我注意到我是否更换了这条线:
for (int idx = 0; idx < LightCount; idx++) //Use 'LightCount' uniform variable
通过以下方式:
for (int idx = 0; idx < 1; idx++) //'1' value hard coded
或
int count = 1;
for (int idx = 0; idx < count; idx++)
着色结果是正确的!
问题似乎来自于我在&#39;中使用统一变量的事实。条件。但是,当我在第一种情况下使用单独的输出变量时,这是有效的!
I checked: the uniform variable 'LightCount' is correct and equal to '1'; (I tried unsigned int data type without success and it's the same thing using a 'while' loop)
你怎么解释这样的结果?
我用:
OpenGL: 4.4.0 NVIDIA driver 344.75
GLSL: 4.40 NVIDIA via Cg compiler
我已经使用了输入/输出数据块而没有问题,但它不是数组,只是简单的块,如下所示:
[in/out] VertexData_VS
{
vec3 viewDir_TS;
vec4 Position_CS;
vec3 Normal_CS;
vec2 TexCoords;
} VertexData_[IN/OUT];
您是否认为在for条件中使用统一变量在循环中使用输入/输出数据块作为数组是不可能的?
更新
我尝试使用2 vec4(为了数据对齐,比如统一块(对于这种情况,数据需要在vec4上对齐))到数据结构中,如下所示:
[in/out] LightData_VS
{
vec4 lightDir_TS; //vec4((TBN * lightDir_CS), 0.0f);
vec4 ShadowCoords;
} LightData_[IN/OUT][MAX_LIGHT_COUNT];
没有成功......
更新2
这是关于着色器编译日志的代码:
core::FileSystem file(filename);
std::ifstream ifs(file.GetFullName());
if (ifs)
{
GLint compilationError = 0;
std::string fileContent, line;
char const *sourceCode;
while (std::getline(ifs, line, '\n'))
fileContent.append(line + '\n');
sourceCode = fileContent.c_str();
ifs.close();
this->m_Handle = glCreateShader(this->m_Type);
glShaderSource(this->m_Handle, 1, &sourceCode, 0);
glCompileShader(this->m_Handle);
glGetShaderiv(this->m_Handle, GL_COMPILE_STATUS, &compilationError);
if (compilationError != GL_TRUE)
{
GLint errorSize = 0;
glGetShaderiv(this->m_Handle, GL_INFO_LOG_LENGTH, &errorSize);
char *errorStr = new char[errorSize + 1];
glGetShaderInfoLog(this->m_Handle, errorSize, &errorSize, errorStr);
errorStr[errorSize] = '\0';
std::cout << errorStr << std::endl;
delete[] errorStr;
glDeleteShader(this->m_Handle);
}
}
关于程序日志的代码:
GLint errorLink = 0;
glGetProgramiv(this->m_Handle, GL_LINK_STATUS, &errorLink);
if (errorLink != GL_TRUE)
{
GLint sizeError = 0;
glGetProgramiv(this->m_Handle, GL_INFO_LOG_LENGTH, &sizeError);
char *error = new char[sizeError + 1];
glGetShaderInfoLog(this->m_Handle, sizeError, &sizeError, error);
error[sizeError] = '\0';
std::cerr << error << std::endl;
glDeleteProgram(this->m_Handle);
delete[] error;
}
不幸的是,我没有任何错误记录!