我需要在OpenGL中创建一个带杆的灯和支架。我需要使用至少2个基本形状和不同的颜色,每个顶点的对象。
出于某种原因,没有任何东西被渲染。有什么不对吗?
下面是我的源代码:
#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
out vec4 vertexColor;
void main()
{
gl_Position = model * vec4(aPos, 1.0);
vertexColor = vec4(1.0, 1.0, 0.0, 1.0); // Yellow color for the lamp
}
)";
const char* fragmentShaderSource = R"(
#version 330 core
in vec4 vertexColor;
out vec4 FragColor;
void main()
{
FragColor = vertexColor;
}
)";
const int sphereSegments = 32; // Number of horizontal segments
const int sphereRings = 16; // Number of vertical rings
const float sphereRadius = 0.2f;
const float poleHeight = 1.5f;
const float poleRadius = 0.025f;
const int poleSegments = 20;
const float baseHeight = 0.1f;
const float baseRadius = 0.3f;
const int baseSegments = 30;
const float shadeRadius = 0.4f;
const float shadeHeight = 0.2f;
const float pi = glm::pi<float>();
void createSphere(std::vector<float>& vertices, std::vector<unsigned int>& indices, float radius, glm::vec4 color) {
const float pi = glm::pi<float>();
const float twoPi = 2.0f * pi;
const float phiStep = pi / static_cast<float>(sphereRings);
const float thetaStep = twoPi / static_cast<float>(sphereSegments);
for (int ring = 0; ring <= sphereRings; ++ring) {
const float phi = ring * phiStep;
for (int segment = 0; segment <= sphereSegments; ++segment) {
const float theta = segment * thetaStep;
const float x = radius * sin(phi) * cos(theta);
const float y = radius * cos(phi);
const float z = radius * sin(phi) * sin(theta);
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
// Color
vertices.push_back(color.r);
vertices.push_back(color.g);
vertices.push_back(color.b);
vertices.push_back(color.a);
}
}
for (int ring = 0; ring < sphereRings; ++ring) {
for (int segment = 0; segment < sphereSegments; ++segment) {
const int currentRow = ring * (sphereSegments + 1);
const int nextRow = (ring + 1) * (sphereSegments + 1);
indices.push_back(currentRow + segment);
indices.push_back(nextRow + segment);
indices.push_back(nextRow + (segment + 1));
indices.push_back(currentRow + segment);
indices.push_back(nextRow + (segment + 1));
indices.push_back(currentRow + (segment + 1));
}
}
}
void createCylinder(std::vector<float>& vertices, std::vector<unsigned int>& indices, float radius, float height, glm::vec4 color) {
const float pi = glm::pi<float>();
const float twoPi = 2.0f * pi;
const float thetaStep = twoPi / static_cast<float>(sphereSegments);
for (int segment = 0; segment <= sphereSegments; ++segment) {
const float theta = segment * thetaStep;
const float x = radius * cos(theta);
const float z = radius * sin(theta);
const float yTop = height / 2.0f;
const float yBottom = -height / 2.0f;
// Top vertex
vertices.push_back(x);
vertices.push_back(yTop);
vertices.push_back(z);
vertices.push_back(color.r);
vertices.push_back(color.g);
vertices.push_back(color.b);
vertices.push_back(color.a);
// Bottom vertex
vertices.push_back(x);
vertices.push_back(yBottom);
vertices.push_back(z);
vertices.push_back(color.r);
vertices.push_back(color.g);
vertices.push_back(color.b);
vertices.push_back(color.a);
if (segment > 0) {
// Triangle 1 indices
indices.push_back((segment - 1) * 2);
indices.push_back(segment * 2);
indices.push_back((segment - 1) * 2 + 1);
// Triangle 2 indices
indices.push_back((segment - 1) * 2 + 1);
indices.push_back(segment * 2);
indices.push_back(segment * 2 + 1);
}
}
}
int main() {
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
// GLFW window and GLEW initialization
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Lamp 3D Model", nullptr, nullptr);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
GLuint vertexShader, fragmentShader, shaderProgram;
// Create and compile the vertex shader
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
// Check for vertex shader compilation errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cerr << "Vertex shader compilation failed:\n" << infoLog << std::endl;
return -1;
}
// Create and compile the fragment shader
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
// Check for fragment shader compilation errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
std::cerr << "Fragment shader compilation failed:\n" << infoLog << std::endl;
return -1;
}
// Create a shader program and link the shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for shader program linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cerr << "Shader program linking failed:\n" << infoLog << std::endl;
return -1;
}
glUseProgram(shaderProgram);
// Define colors for lamp components
glm::vec4 baseColor = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f); // Gray
glm::vec4 poleColor = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f); // Gray
glm::vec4 shadeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f); // Yellow
// Create lamp components
std::vector<float> baseVertices;
std::vector<unsigned int> baseIndices;
createSphere(baseVertices, baseIndices, baseRadius, baseColor);
std::vector<float> poleVertices;
std::vector<unsigned int> poleIndices;
createCylinder(poleVertices, poleIndices, poleRadius, poleHeight, poleColor);
std::vector<float> shadeVertices;
std::vector<unsigned int> shadeIndices;
createSphere(shadeVertices, shadeIndices, shadeRadius, shadeColor);
GLuint baseVAO, baseVBO, baseEBO;
GLuint poleVAO, poleVBO, poleEBO;
GLuint shadeVAO, shadeVBO, shadeEBO;
// Initialize base VAO, VBO, and EBO
glGenVertexArrays(1, &baseVAO);
glBindVertexArray(baseVAO);
glGenBuffers(1, &baseVBO);
glBindBuffer(GL_ARRAY_BUFFER, baseVBO);
glBufferData(GL_ARRAY_BUFFER, baseVertices.size() * sizeof(float), &baseVertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &baseEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, baseEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, baseIndices.size() * sizeof(unsigned int), &baseIndices[0], GL_STATIC_DRAW);
// Set vertex attribute pointers for base
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Initialize pole VAO, VBO, and EBO
glGenVertexArrays(1, &poleVAO);
glBindVertexArray(poleVAO);
glGenBuffers(1, &poleVBO);
glBindBuffer(GL_ARRAY_BUFFER, poleVBO);
glBufferData(GL_ARRAY_BUFFER, poleVertices.size() * sizeof(float), &poleVertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &poleEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, poleEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, poleIndices.size() * sizeof(unsigned int), &poleIndices[0], GL_STATIC_DRAW);
// Set vertex attribute pointers for pole
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Initialize shade VAO, VBO, and EBO
glGenVertexArrays(1, &shadeVAO);
glBindVertexArray(shadeVAO);
glGenBuffers(1, &shadeVBO);
glBindBuffer(GL_ARRAY_BUFFER, shadeVBO);
glBufferData(GL_ARRAY_BUFFER, shadeVertices.size() * sizeof(float), &shadeVertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &shadeEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shadeEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, shadeIndices.size() * sizeof(unsigned int), &shadeIndices[0], GL_STATIC_DRAW);
// Set vertex attribute pointers for shade
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Rendering loop
while (!glfwWindowShouldClose(window)) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
// Set transformation matrices for the lamp components
glm::mat4 model;
// Base transformation
model = glm::translate(model, glm::vec3(0.0f, -1.0f, 0.0f));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(baseVAO);
glDrawElements(GL_TRIANGLES, baseIndices.size(), GL_UNSIGNED_INT, 0);
// Pole transformation
model = glm::mat4(); // Reset model matrix
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); // Adjust position
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(poleVAO);
glDrawElements(GL_TRIANGLES, poleIndices.size(), GL_UNSIGNED_INT, 0);
// Shade transformation
model = glm::mat4(); // Reset model matrix
model = glm::translate(model, glm::vec3(0.0f, 1.0f, 0.0f)); // Adjust position
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(shadeVAO);
glDrawElements(GL_TRIANGLES, shadeIndices.size(), GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
// Clean up and terminate GLFW
glDeleteVertexArrays(1, &baseVAO);
glDeleteBuffers(1, &baseVBO);
glDeleteBuffers(1, &baseEBO);
glDeleteVertexArrays(1, &poleVAO);
glDeleteBuffers(1, &poleVBO);
glDeleteBuffers(1, &poleEBO);
glDeleteVertexArrays(1, &shadeVAO);
glDeleteBuffers(1, &shadeVBO);
glDeleteBuffers(1, &shadeEBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
1条答案
按热度按时间oprakyz71#
几个问题:
glm::mat4 model;
这样的东西会给予你一个未初始化的,可能是垃圾的矩阵。另外,像model = glm::mat4();
这样的东西会给予一个zero matrix,这也不是您想要用来启动转换管道的东西。使用
glm::mat4 model = glm::mat4(1);
得到identity matrix。createSphere()
和createCylinder()
都为每个顶点发出四个浮点值的颜色,每个顶点总共有7个浮点值。然而,所有的glVertexAttribPointer()
调用都声称3 * sizeof(float)
的 * 步幅 *。删除颜色数据或将 strides切换为
7 * sizeof(float)
。所有这些(切换到GLAD,因为这是我在系统上运行的):