C++ Can';无法在OpenGL中获取分配给属性的ID
我试图让OpenGL自动为glsl属性分配一个ID,但失败了 我的主要节目:C++ Can';无法在OpenGL中获取分配给属性的ID,c++,c,opengl,glsl,shader,C++,C,Opengl,Glsl,Shader,我试图让OpenGL自动为glsl属性分配一个ID,但失败了 我的主要节目: #include <iostream> #include <GL/glew.h> #include <GL/glfw3.h> #include "test.h" #include "shader_utils.h" static void error_callback(int error, const char* description) { std::cout <
#include <iostream>
#include <GL/glew.h>
#include <GL/glfw3.h>
#include "test.h"
#include "shader_utils.h"
static void error_callback(int error, const char* description) {
std::cout << description << std::endl;
}
static void key_callback(GLFWwindow* window, int a, int b) {
if (a == GLFW_KEY_ESCAPE && b == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
void test()
{
std::cout << "Starting up" << std::endl;
init();
run();
}
GLFWwindow *window;
GLuint shaders;
GLuint vertexBuffer;
int init() {
glfwSetErrorCallback(error_callback);
if(!glfwInit()) {
return -1;
}
window = glfwCreateWindow(640, 480, "GLFW test", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glewExperimental = true;
glewInit();
shaders = LoadShaders("vertex.glsl", "fragment.glsl");
GLuint vao_id;
glGenVertexArrays(1, &vao_id);
glBindVertexArray(vao_id);
static const GLfloat vertex_data[] = {
// Bottom
-.5f, -.5f, -.5f, 1.f, 0.f, 0.f,
-.5f, -.5f, .5f, 1.f, 0.f, 0.f,
.5f, -.5f, .5f, 1.f, 0.f, 0.f,
};
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
}
void checkE() {
std::cout << "Checking for errors: ";
int err;
int a = 0;
while((err = glGetError()) != GL_NO_ERROR) {
std::cout << "Error: " << err << std::endl;
a = 1;
}
if(a == 0) {
std::cout << "no errors" << std::endl;
}
std::cout.flush();
}
int run() {
GLfloat angle = 0;
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaders);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLuint attrLocation = glGetAttribLocation(shaders, "location");
GLuint attrColor = glGetAttribLocation(shaders, "color");
std::cout << "AttribLocation('location'): ";
std::cout << glGetAttribLocation(shaders, "location") << std::endl;
std::cout << "AttribLocation('color'): ";
std::cout << glGetAttribLocation(shaders, "color") << std::endl;
checkE();
std::cout << std::endl;
std::cout << "glEnableVertexAttribArray()" << std::endl;
glEnableVertexAttribArray(attrLocation);
glEnableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "location"), // Attribute
3, // Size
GL_FLOAT, // Size
GL_FALSE, // Normalized
24, // Stride
(GLvoid*) 0 // Offset
);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "color"),
3,
GL_FLOAT,
GL_FALSE,
24,
(GLvoid*) (3*sizeof(GLfloat))
);
checkE();
std::cout << std::endl;
glDrawArrays(GL_TRIANGLES, 0, 3);
checkE();
std::cout << std::endl;
glDisableVertexAttribArray(attrLocation);
glDisableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
glfwSwapBuffers(window);
glfwPollEvents();
glfwSetWindowShouldClose(window, GL_TRUE);
}
glfwDestroyWindow(window);
glfwTerminate();
}
着色器加载程序:
#include "shader_utils.h"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "GL/glew.h"
#include "GL/glfw3.h"
GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open())
{
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
} else {
std::cout << "could not open\n";
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
std::cout.flush();
return ProgramID;
}
片段着色器:
#version 130
in vec3 color;
void main() {
gl_FragColor = vec4(color, 1);
}
出于某种原因,我只得到-1
作为这两个属性的位置。显然,其余的错误是由无效的位置索引引起的
来自OpenGL文档:如果指定的属性变量不是指定程序对象中的活动属性,或者如果名称以保留前缀“gl_”开头,则返回值-1。
名称不是以
gl\uuu
开头,它们在着色器中使用,因此我不应该得到-1
的值。我遗漏了什么?您无法获取颜色的属性位置,因为它不处于活动状态。虽然在本例中,color
确实用于计算f_color
,但片段着色器不使用f_color
,因此链接器确定名为:color
的顶点属性处于非活动状态
解决方案非常简单,真的:
片段着色器:
在顶点着色器(输入顶点属性)和片段着色器(输入变化)阶段中,为不同目的重复使用名称颜色
,这样编译器/链接器就不会抱怨了,这不是错误。但是,如果尝试执行类似于inout color的操作,则会出现错误,因此,必须使用不同名称的变量将顶点属性传递给几何体/细分/碎片着色器。如果阶段之间的输入/输出名称不匹配,则很有可能原始顶点属性被视为处于非活动状态
此外,除非要转置ModelViewProjection矩阵,否则顶点着色器中的矩阵乘法将向后。列主矩阵乘法,就像OpenGL使用的那样,应该从右向左读取。也就是说,从对象空间位置(最右侧)开始,变换到剪辑空间(最左侧)
换句话说,这是变换顶点的正确方法
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space
您无法获取颜色的属性位置,因为它未处于活动状态。虽然在本例中,color
确实用于计算f_color
,但片段着色器不使用f_color
,因此链接器确定名为:color
的顶点属性处于非活动状态
解决方案非常简单,真的:
片段着色器:
在顶点着色器(输入顶点属性)和片段着色器(输入变化)阶段中,为不同目的重复使用名称颜色
,这样编译器/链接器就不会抱怨了,这不是错误。但是,如果尝试执行类似于inout color的操作,则会出现错误,因此,必须使用不同名称的变量将顶点属性传递给几何体/细分/碎片着色器。如果阶段之间的输入/输出名称不匹配,则很有可能原始顶点属性被视为处于非活动状态
此外,除非要转置ModelViewProjection矩阵,否则顶点着色器中的矩阵乘法将向后。列主矩阵乘法,就像OpenGL使用的那样,应该从右向左读取。也就是说,从对象空间位置(最右侧)开始,变换到剪辑空间(最左侧)
换句话说,这是变换顶点的正确方法
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space
您无法获取颜色的属性位置,因为它未处于活动状态。虽然在本例中,color
确实用于计算f_color
,但片段着色器不使用f_color
,因此链接器确定名为:color
的顶点属性处于非活动状态
解决方案非常简单,真的:
片段着色器:
在顶点着色器(输入顶点属性)和片段着色器(输入变化)阶段中,为不同目的重复使用名称颜色
,这样编译器/链接器就不会抱怨了,这不是错误。但是,如果尝试执行类似于inout color的操作,则会出现错误,因此,必须使用不同名称的变量将顶点属性传递给几何体/细分/碎片着色器。如果阶段之间的输入/输出名称不匹配,则很有可能原始顶点属性被视为处于非活动状态
此外,除非要转置ModelViewProjection矩阵,否则顶点着色器中的矩阵乘法将向后。列主矩阵乘法,就像OpenGL使用的那样,应该从右向左读取。也就是说,从对象空间位置(最右侧)开始,变换到剪辑空间(最左侧)
换句话说,这是变换顶点的正确方法
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space
您无法获取颜色的属性位置,因为它未处于活动状态。虽然在本例中,color
确实用于计算f_color
,但片段着色器不使用f_color
,因此链接器确定名为:color
的顶点属性处于非活动状态
解决方案非常简单,真的:
片段着色器:
在顶点着色器(输入顶点属性)和片段着色器(输入变化)阶段中,为不同目的重复使用名称颜色
,这样编译器/链接器就不会抱怨了,这不是错误。但是,如果您尝试执行类似于inout color的操作,则会出现错误,因此,这就是为什么必须使用不同的na将顶点属性传递给几何体/细分/片段着色器的原因
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space