我已成功为OpenGL设置着色器和测试三角形。我想设置一个可以在顶点着色器中应用的变换均匀。问题是,在我将vec4位置与mat4变换相乘后,我再也看不到我的物体了。我在哪里做错了什么?
顶点着色器:
#version 120
attribute vec3 vertices;
attribute vec3 colors;
attribute vec2 texCoords;
uniform mat4 transform;
varying vec3 shared_colors;
varying vec2 shared_texCoords;
void main() {
gl_Position = transform * vec4(vertices, 1.0);
//Send data to fragment shader
shared_colors = colors;
shared_texCoords = texCoords;
}
片段着色器:
#version 120
uniform sampler2D diffuse;
varying vec3 shared_colors;
varying vec2 shared_texCoords;
void main() {
gl_FragColor = vec4(shared_colors, 1);
//gl_FragColor = texture2D(diffuse, shared_texCoords); //vec4(1, 0, 0, 1);
}
着色器类:
#include "Shader.h"
Shader::Shader(string fileName) {
m_program = glCreateProgram();
m_shaders[SHA_VERTEX] = createShader(loadShader(fileName + ".vs"), GL_VERTEX_SHADER);
m_shaders[SHA_FRAGMENT] = createShader(loadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);
for (int i = 0; i < SHA_COUNT; i++) {
glAttachShader(m_program, m_shaders[i]);
}
glBindAttribLocation(m_program, VBO_VERTEX, "vertices");
glBindAttribLocation(m_program, VBO_COLOR, "colors");
glBindAttribLocation(m_program, VBO_TEXCORD, "texCoords");
glLinkProgram(m_program);
checkShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");
glValidateProgram(m_program);
checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");
m_uniforms[UNI_TRANSFORM] = glGetUniformLocation(m_program, "transform");
}
Shader::~Shader() {
for (int i = 0; i < SHA_COUNT; i++) {
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
string Shader::loadShader(string filePath) {
ifstream file;
file.open((filePath).c_str());
string output;
string line;
if(file.is_open()) {
while(file.good()) {
getline(file, line);
output.append(line + "\n");
}
}
else {
printf("Unable to load shader: %s\n", filePath.c_str());
}
return output;
}
void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, string errorMessage) {
GLint success = 0;
GLchar error[1024] = {0};
if (isProgram) {
glGetProgramiv(shader, flag, &success);
}
else {
glGetShaderiv(shader, flag, &success);
}
if (success == GL_FALSE) {
if(isProgram) {
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
}
else {
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
}
printf("%s: '%s'\n", errorMessage.c_str(), error);
}
}
GLuint Shader::createShader(string text, unsigned int type) {
GLuint shader = glCreateShader(type);
if (shader == 0) {
printf("Error compiling shader type %i\n", type);
}
const GLchar *p[1];
p[0] = text.c_str();
GLint lengths[1];
lengths[0] = text.length();
glShaderSource(shader, 1, p, lengths);
glCompileShader(shader);
checkShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!");
return shader;
}
void Shader::update(Transform *matrix) {
glm::mat4 model = matrix->getModel();
glUniformMatrix4fv(m_uniforms[UNI_TRANSFORM], 1, GL_FALSE, &model[0][0]);
}
void Shader::enable(bool state) {
if (state) {
glUseProgram(m_program);
}
else {
glUseProgram(NULL);
}
}
Mesh类(或者,如果您更喜欢称之为我的对象类):
#include "Mesh.h"
Mesh::Mesh() {
initMesh();
}
Mesh::Mesh(ObjectData *obj) {
initMesh();
//Set object to parameter
object = obj;
initVBO();
}
Mesh::~Mesh() {
delete transform;
//Delete buffer
glDeleteBuffers(VBO_COUNT, buffers);
//Delete array
glDeleteVertexArrays(1, &arrayObject);
}
void Mesh::draw() {
if (initialized) {
shader->update(transform);
shader->enable(true);
texture->enable(true);
//Tell OpenGL which array to use
glBindVertexArray(arrayObject);
glDrawArrays(GL_TRIANGLES, 0, object->vertices.size());
glBindVertexArray(NULL);
shader->enable(false);
texture->enable(false);
}
}
void Mesh::initMesh() {
initialized = false;
shader = new Shader(DIR_SHADERS + "BasicShader");
transform = new Transform();
}
void Mesh::initVBO() {
glGenVertexArrays(1, &arrayObject);
//Tell OpenGL which vertex array to use from now
glBindVertexArray(arrayObject);
glGenBuffers(VBO_COUNT, buffers);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_VERTEX);
glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_COLOR]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->colors.size(), &object->colors.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_COLOR);
glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
if (object->texCoords.size()) {
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_TEXCORD);
glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Unbind vertex array
glBindVertexArray(NULL);
initialized = true;
}
void Mesh::updateVBO() {
//Tell OpenGL which vertex array to use from now
glBindVertexArray(arrayObject);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_VERTEX);
glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_COLOR]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->colors.size(), &object->colors.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_COLOR);
glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
if (object->texCoords.size()) {
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_TEXCORD);
glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Unbind vertex array
glBindVertexArray(NULL);
}
void Mesh::setShader(string file) {
shader = new Shader(file);
}
void Mesh::setTexture(string file) {
texture = new Texture(file);
}
void Mesh::loadObject(string file) {
//Example object
object = new ObjectData();
object->vertices.push_back(glm::vec3(-0.5, -0.5, 0));
object->vertices.push_back(glm::vec3(0, 0.5, 0));
object->vertices.push_back(glm::vec3(0.5, -0.5, 0));
//object->texCoords.push_back(glm::vec2(0, 0));
//object->texCoords.push_back(glm::vec2(0.5, 1));
//object->texCoords.push_back(glm::vec2(1, 0));
object->colors.push_back(glm::vec3(255, 0, 0));
object->colors.push_back(glm::vec3(255, 0, 0));
object->colors.push_back(glm::vec3(255, 0, 0));
//object->vertices.push_back(glm::vec3(0.5, 0.5, 0));
//object->vertices.push_back(glm::vec3(0.75, 1, 0));
//object->vertices.push_back(glm::vec3(1, 0.5, 0));
//object->texCoords.push_back(glm::vec2(0, 0));
//object->texCoords.push_back(glm::vec2(0.5, 1));
//object->texCoords.push_back(glm::vec2(1, 0));
//object->colors.push_back(glm::vec3(0, 255, 0));
//object->colors.push_back(glm::vec3(0, 255, 0));
//object->colors.push_back(glm::vec3(0, 255, 0));
if (initialized) {
updateVBO();
}
else {
initVBO();
}
}
转换类:
#include "Transform.h"
Transform::Transform() {
position = glm::vec3();
rotation = glm::vec3();
scale = glm::vec3(1, 1, 1);
}
Transform::~Transform() {
}
void Transform::setPosition(glm::vec3 pos) {
position = pos;
}
void Transform::setRotation(glm::vec3 rot) {
rotation = rot;
}
void Transform::setScale(glm::vec3 sca) {
scale = sca;
}
glm::vec3 Transform::getPosition() {
return position;
}
glm::vec3 Transform::getRotation() {
return rotation;
}
glm::vec3 Transform::getScale() {
return scale;
}
glm::mat4 Transform::getModel() {
glm::mat4 pos = glm::translate(position);
glm::mat4 rotX = glm::rotate(rotation.x, glm::vec3(1, 0, 0));
glm::mat4 rotY = glm::rotate(rotation.y, glm::vec3(0, 1, 0));
glm::mat4 rotZ = glm::rotate(rotation.z, glm::vec3(0, 0, 1));
glm::mat4 sca = glm::scale(scale);
glm::mat4 rot = rotZ * rotY * rotX;
glm::mat4 finalMatrix = pos * rot * sca;
return finalMatrix;
}
答案 0 :(得分:1)
从你的代码:
void Mesh::draw() {
if (initialized) {
shader->update(transform);
shader->enable(true);
GL制服是每个程序状态,设置制服会影响当前绑定的程序对象。由于在尝试设置制服时没有绑定程序对象,因此统一处于默认状态(全为零)。只需切换这两行......