Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

I managed to wrap the texture on my pyramid but 2 sides don't show bricks but seem stretched to stripes. I can not find the

I managed to wrap the texture on my pyramid but 2 sides don't show bricks but seem stretched to stripes. I can not find the error in my code. Please help! Also I set a key light and a fill light from different angles but don't see much difference. Can you see it? I think the texture should be brown brick but the light makes everything just green. How can I change the texture is still brown but the light green? #include // cout, cerr #include // EXIT_FAILURE #include // GLEW library #include // GLFW library #define STB_IMAGE_IMPLEMENTATION #include // Image loading Utility functions

// GLM Math Header inclusions #include #include #include #include

#include // Camera class

using namespace std; // Standard namespace

/*Shader program Macro*/ #ifndef GLSL #define GLSL(Version, Source) "#version " #Version " core " #Source #endif

// Unnamed namespace namespace { const char* const WINDOW_TITLE = "Textured pyramid with light"; // Macro for window title

// Variables for window width and height const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600;

// Stores the GL data relative to a given mesh struct GLMesh { GLuint vao; // Handle for the vertex array object GLuint vbo; // Handle for the vertex buffer object GLuint nVertices; // Number of indices of the mesh };

// Main GLFW window GLFWwindow* gWindow = nullptr; // Triangle mesh data GLMesh gMesh;

// Texture GLuint gTextureId; glm::vec2 gUVScale(5.0f, 5.0f); GLint gTexWrapMode = GL_REPEAT;

// Shader program GLuint gProgramId; GLuint gLampProgramId;

// camera Camera gCamera(glm::vec3(1.0f, 1.0f, 3.0f)); float gLastX = WINDOW_WIDTH / 2.0f; float gLastY = WINDOW_HEIGHT / 2.0f; bool gFirstMouse = true;

// timing float gDeltaTime = 0.0f; // time between current frame and last frame float gLastFrame = 0.0f;

// Subject position and scale glm::vec3 gPyramidPosition(0.0f, 0.0f, 0.0f); glm::vec3 gPyramidScale(2.0f);

// Pyramid and light color //m::vec3 gObjectColor(0.6f, 0.5f, 0.75f); glm::vec3 gObjectColor(1.f, 0.2f, 0.0f); glm::vec3 gLightColor(0.0f, 1.0f, 0.0f);

// Key Light position and scale glm::vec3 gLightPosition(1.5f, 7.5f, 4.0f); //adjusts the key light glm::vec3 gLightScale(0.3f); }

/* User-defined Function prototypes to: * initialize the program, set the window size, * redraw graphics on the window when resized, * and render graphics on the screen */ bool UInitialize(int, char*[], GLFWwindow** window); void UResizeWindow(GLFWwindow* window, int width, int height); void UProcessInput(GLFWwindow* window); void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos); void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset); void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods); void UCreateMesh(GLMesh &mesh); void UDestroyMesh(GLMesh &mesh); bool UCreateTexture(const char* filename, GLuint &textureId); void UDestroyTexture(GLuint textureId); void URender(); bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint &programId); void UDestroyShaderProgram(GLuint programId);

/* Pyramid Vertex Shader Source Code*/ const GLchar * pyramidVertexShaderSource = GLSL(440, layout (location = 0) in vec3 position; layout(location = 1) in vec3 normal; // VAP position 1 for normals layout (location = 2) in vec2 textureCoordinate;

out vec3 vertexNormal; // For outgoing normals to fragment shader out vec3 vertexFragmentPos; // For outgoing color / pixels to fragment shader out vec2 vertexTextureCoordinate;

//Global variables for the transform matrices uniform mat4 model; uniform mat4 view; uniform mat4 projection;

void main() { gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates

vertexFragmentPos = vec3(model * vec4(position, 1.0f)); // Gets fragment / pixel position in world space only (exclude view and projection)

vertexNormal = mat3(transpose(inverse(model))) * normal; // get normal vectors in world space only and exclude normal translation properties

vertexTextureCoordinate = textureCoordinate; } );

/* Pyramid Fragment Shader Source Code*/ const GLchar * pyramidFragmentShaderSource = GLSL(440,

in vec3 vertexNormal; // For incoming normals in vec3 vertexFragmentPos; // For incoming fragment position in vec2 vertexTextureCoordinate;

out vec4 fragmentColor;

// Uniform / Global variables for object color, key light color, key light position, and camera/view position uniform vec3 objectColor; uniform vec3 lightColor; uniform vec3 lightPos; uniform vec3 viewPosition; uniform sampler2D uTexture; uniform vec2 uvScale;

void main() { // Adjust the strengths for key and fill lights float keyLightStrength = 1.0; // 100% float fillLightStrength = 0.1; // 10%

// Ambient lighting float ambientStrength = 3.0f; vec3 ambient = ambientStrength * lightColor;

// Diffuse lighting (key light) vec3 norm = normalize(vertexNormal); vec3 lightDir = normalize(lightPos - vertexFragmentPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = keyLightStrength * diff * lightColor;

// Fill light contribution (reduce contrast) vec3 fillLightPos = vec3(4.0, 2.0, 0.0); // Adjust the position of the fill light vec3 fillLightDir = normalize(fillLightPos - vertexFragmentPos); vec3 fillDiffuse = fillLightStrength * max(dot(norm, fillLightDir), 0.0) * lightColor;

// Specular lighting float specularStrength = 0.5; vec3 viewDir = normalize(viewPosition - vertexFragmentPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0); vec3 specular = specularStrength * spec * lightColor;

// Combine key and fill light contributions vec3 result = (ambient + diffuse + specular) * objectColor.rgb + fillDiffuse;

fragmentColor = texture(uTexture, vertexTextureCoordinate * uvScale) * vec4(result, 1.0); } );

// Images are loaded with Y axis going down, but OpenGL's Y axis goes up, so let's flip it void flipImageVertically(unsigned char *image, int width, int height, int channels) { for (int j = 0; j < height / 2; ++j) { int index1 = j * width * channels; int index2 = (height - 1 - j) * width * channels;

for (int i = width * channels; i > 0; --i) { unsigned char tmp = image[index1]; image[index1] = image[index2]; image[index2] = tmp; ++index1; ++index2; } } }

int main(int argc, char* argv[]) { if (!UInitialize(argc, argv, &gWindow)) return EXIT_FAILURE;

//build the mesh UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object

// build the shader program if (!UCreateShaderProgram(pyramidVertexShaderSource, pyramidFragmentShaderSource, gProgramId)) return EXIT_FAILURE;

// Load texture const char * texFilename = "../../resources/textures/wall.jpg"; if (!UCreateTexture(texFilename, gTextureId)) { cout << "Failed to load texture " << texFilename << endl; return EXIT_FAILURE; } // tell opengl for each sampler to which texture unit it belongs to (only has to be done once) glUseProgram(gProgramId); // We set the texture as texture unit 0 glUniform1i(glGetUniformLocation(gProgramId, "uTexture"), 0);

// Sets the background color of the window to black (it will be implicitely used by glClear) glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

// render loop // ----------- while (!glfwWindowShouldClose(gWindow)) { // per-frame timing // -------------------- float currentFrame = glfwGetTime(); gDeltaTime = currentFrame - gLastFrame; gLastFrame = currentFrame;

// input // ----- UProcessInput(gWindow);

// Render this frame URender();

glfwPollEvents(); }

// Release mesh data UDestroyMesh(gMesh);

// Release texture UDestroyTexture(gTextureId);

// Release shader program UDestroyShaderProgram(gProgramId);

exit(EXIT_SUCCESS); // Terminates the program successfully }

// Initialize GLFW, GLEW, and create a window bool UInitialize(int argc, char* argv[], GLFWwindow** window) { // GLFW: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif

// GLFW: window creation // --------------------- *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL); if (*window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return false; } glfwMakeContextCurrent(*window); glfwSetFramebufferSizeCallback(*window, UResizeWindow); glfwSetCursorPosCallback(*window, UMousePositionCallback); glfwSetScrollCallback(*window, UMouseScrollCallback); glfwSetMouseButtonCallback(*window, UMouseButtonCallback);

// tell GLFW to capture our mouse glfwSetInputMode(*window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

// GLEW: initialize // ---------------- // Note: if using GLEW version 1.13 or earlier glewExperimental = GL_TRUE; GLenum GlewInitResult = glewInit();

if (GLEW_OK != GlewInitResult) { std::cerr << glewGetErrorString(GlewInitResult) << std::endl; return false; }

// Displays GPU OpenGL version cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;

return true; }

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly void UProcessInput(GLFWwindow* window) { static const float cameraSpeed = 2.5f;

if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true);

if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) gCamera.ProcessKeyboard(FORWARD, gDeltaTime); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) gCamera.ProcessKeyboard(BACKWARD, gDeltaTime); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) gCamera.ProcessKeyboard(LEFT, gDeltaTime); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) gCamera.ProcessKeyboard(RIGHT, gDeltaTime);

if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS && gTexWrapMode != GL_REPEAT) { glBindTexture(GL_TEXTURE_2D, gTextureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0);

gTexWrapMode = GL_REPEAT;

cout << "Current Texture Wrapping Mode: REPEAT" << endl; } else if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS && gTexWrapMode != GL_MIRRORED_REPEAT) { glBindTexture(GL_TEXTURE_2D, gTextureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); glBindTexture(GL_TEXTURE_2D, 0);

gTexWrapMode = GL_MIRRORED_REPEAT;

cout << "Current Texture Wrapping Mode: MIRRORED REPEAT" << endl; } else if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS && gTexWrapMode != GL_CLAMP_TO_EDGE) { glBindTexture(GL_TEXTURE_2D, gTextureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0);

gTexWrapMode = GL_CLAMP_TO_EDGE;

cout << "Current Texture Wrapping Mode: CLAMP TO EDGE" << endl; } else if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS && gTexWrapMode != GL_CLAMP_TO_BORDER) { float color[] = {1.0f, 0.0f, 1.0f, 1.0f}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);

glBindTexture(GL_TEXTURE_2D, gTextureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glBindTexture(GL_TEXTURE_2D, 0);

gTexWrapMode = GL_CLAMP_TO_BORDER;

cout << "Current Texture Wrapping Mode: CLAMP TO BORDER" << endl; }

if (glfwGetKey(window, GLFW_KEY_RIGHT_BRACKET) == GLFW_PRESS) { gUVScale += 0.1f; cout << "Current scale (" << gUVScale[0] << ", " << gUVScale[1] << ")" << endl; } else if (glfwGetKey(window, GLFW_KEY_LEFT_BRACKET) == GLFW_PRESS) { gUVScale -= 0.1f; cout << "Current scale (" << gUVScale[0] << ", " << gUVScale[1] << ")" << endl; } }

// glfw: whenever the window size changed (by OS or user resize) this callback function executes void UResizeWindow(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }

// glfw: whenever the mouse moves, this callback is called // ------------------------------------------------------- void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos) { if (gFirstMouse) { gLastX = xpos; gLastY = ypos; gFirstMouse = false; }

float xoffset = xpos - gLastX; float yoffset = gLastY - ypos; // reversed since y-coordinates go from bottom to top

gLastX = xpos; gLastY = ypos;

gCamera.ProcessMouseMovement(xoffset, yoffset); }

// glfw: whenever the mouse scroll wheel scrolls, this callback is called // ---------------------------------------------------------------------- void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset) { gCamera.ProcessMouseScroll(yoffset); }

// glfw: handle mouse button events // -------------------------------- void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { switch (button) { case GLFW_MOUSE_BUTTON_LEFT: { if (action == GLFW_PRESS) cout << "Left mouse button pressed" << endl; else cout << "Left mouse button released" << endl; } break;

case GLFW_MOUSE_BUTTON_MIDDLE: { if (action == GLFW_PRESS) cout << "Middle mouse button pressed" << endl; else cout << "Middle mouse button released" << endl; } break;

case GLFW_MOUSE_BUTTON_RIGHT: { if (action == GLFW_PRESS) cout << "Right mouse button pressed" << endl; else cout << "Right mouse button released" << endl; } break;

default: cout << "Unhandled mouse button event" << endl; break; } }

// Functioned called to render a frame void URender() { // Enable z-depth glEnable(GL_DEPTH_TEST); // Clear the frame and z buffers glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

float scaler = 1.0f; glm::mat4 scale = glm::scale(glm::vec3(scaler)); glm::mat4 rotation = glm::rotate(glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); // Rotate by 45 degrees in the x-axis glm::vec3 location = glm::vec3(0.0f, 0.0f, 0.0f); glm::mat4 translation = glm::translate(location); glm::mat4 model = translation * rotation * scale;

// camera/view transformation glm::mat4 view = gCamera.GetViewMatrix();

// Creates a perspective projection glm::mat4 projection = glm::perspective(glm::radians(gCamera.Zoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);

// Set the shader to be used glUseProgram(gProgramId);

// Retrieves and passes transform matrices to the Shader program GLint modelLoc = glGetUniformLocation(gProgramId, "model"); GLint viewLoc = glGetUniformLocation(gProgramId, "view"); GLint projLoc = glGetUniformLocation(gProgramId, "projection");

glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

// Set lighting uniforms GLint objectColorLoc = glGetUniformLocation(gProgramId, "objectColor"); GLint lightColorLoc = glGetUniformLocation(gProgramId, "lightColor"); GLint lightPosLoc = glGetUniformLocation(gProgramId, "lightPos"); GLint viewPosLoc = glGetUniformLocation(gProgramId, "viewPosition");

glUniform3fv(objectColorLoc, 1, glm::value_ptr(gObjectColor)); glUniform3fv(lightColorLoc, 1, glm::value_ptr(gLightColor)); glUniform3fv(lightPosLoc, 1, glm::value_ptr(gLightPosition)); glUniform3fv(viewPosLoc, 1, glm::value_ptr(gCamera.Position));

GLint UVScaleLoc = glGetUniformLocation(gProgramId, "uvScale"); glUniform2fv(UVScaleLoc, 1, glm::value_ptr(gUVScale));

// Activate the VBOs contained within the mesh's VAO glBindVertexArray(gMesh.vao);

// bind textures on corresponding texture units glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gTextureId);

// Draws the triangles glDrawArrays(GL_TRIANGLES, 0, gMesh.nVertices);

// Deactivate the Vertex Array Object glBindVertexArray(0);

// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame. }

// Implements the UCreateMesh function void UCreateMesh(GLMesh &mesh) { GLfloat verts[] = { // Positions // Texture Coordinates 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // Left Bottom Vertex 1 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2

0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // Left Bottom Vertex 1 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3

0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // Right Top Vertex 4

0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // Right Top Vertex 4

1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // Right Top Vertex 4 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2 -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // Left Bottom Vertex 1 };

// Calculate normals std::vector normals; for (size_t i = 0; i < sizeof(verts) / (5 * sizeof(float)); i += 3) { glm::vec3 v1(verts[i], verts[i + 1], verts[i + 2]); glm::vec3 v2(verts[i + 3], verts[i + 4], verts[i + 5]); glm::vec3 v3(verts[i + 6], verts[i + 7], verts[i + 8]);

glm::vec3 normal = glm::normalize(glm::cross(v2 - v1, v3 - v1));

normals.push_back(normal); normals.push_back(normal); normals.push_back(normal); }

const GLuint floatsPerVertex = 3; const GLuint floatsPerUV = 2;

mesh.nVertices = sizeof(verts) / (sizeof(verts[0]) * (floatsPerVertex + floatsPerUV));

glGenVertexArrays(1, &mesh.vao); glBindVertexArray(mesh.vao);

glGenBuffers(1, &mesh.vbo); glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

GLint stride = sizeof(float) * (floatsPerVertex + floatsPerUV);

glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0); glEnableVertexAttribArray(0);

glVertexAttribPointer(2, floatsPerUV, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(float) * floatsPerVertex)); glEnableVertexAttribArray(2);

// Generate and bind a normal buffer GLuint normalBuffer; glGenBuffers(1, &normalBuffer); glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW);

// Set up the normal attribute glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0); glEnableVertexAttribArray(1);

// Vertex Data /*GLfloat verts[] = { //Positions //Texture Coordinates 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // Left Bottom Vertex 1 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2

0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // Left Bottom Vertex 1 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3

0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // Right Top Vertex 4

0.0f, 0.0f, 2.0f, 0.0f, 0.0f, // Front Vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // Right Top Vertex 4

1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // Right Top Vertex 4 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Right Bottom Vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Left Top Vertex 2 -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // Left Bottom Vertex 1 };

const GLuint floatsPerVertex = 3; const GLuint floatsPerUV = 2;

mesh.nVertices = sizeof(verts) / (sizeof(verts[0]) * (floatsPerVertex + floatsPerUV));

glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time glBindVertexArray(mesh.vao);

// Create VBO glGenBuffers(1, &mesh.vbo); glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo); // Activates the buffer glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU

// Strides between vertex coordinates GLint stride = sizeof(float) * (floatsPerVertex + floatsPerUV);

// Create Vertex Attribute Pointers glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0); glEnableVertexAttribArray(0);

glVertexAttribPointer(2, floatsPerUV, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(float) * floatsPerVertex)); glEnableVertexAttribArray(2);*/ }

void UDestroyMesh(GLMesh &mesh) { glDeleteVertexArrays(1, &mesh.vao); glDeleteBuffers(1, &mesh.vbo); }

/*Generate and load the texture*/ bool UCreateTexture(const char* filename, GLuint &textureId) { int width, height, channels; unsigned char *image = stbi_load(filename, &width, &height, &channels, 0); if (image) { flipImageVertically(image, width, height, channels);

glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId);

// set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

if (channels == 3) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); else if (channels == 4) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); else { cout << "Not implemented to handle image with " << channels << " channels" << endl; return false; }

glGenerateMipmap(GL_TEXTURE_2D);

stbi_image_free(image); glBindTexture(GL_TEXTURE_2D, 0); // Unbind the texture

return true; }

// Error loading the image return false; }

void UDestroyTexture(GLuint textureId) { glGenTextures(1, &textureId); }

// Implements the UCreateShaders function bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint &programId) { // Compilation and linkage error reporting int success = 0; char infoLog[512];

// Create a Shader program object. programId = glCreateProgram();

// Create the vertex and fragment shader objects GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);

// Retrive the shader source glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL); glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);

// Compile the vertex shader, and print compilation errors (if any) glCompileShader(vertexShaderId); // compile the vertex shader // check for shader compile errors glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED " << infoLog << std::endl;

return false; }

glCompileShader(fragmentShaderId); // compile the fragment shader // check for shader compile errors glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED " << infoLog << std::endl;

return false; }

// Attached compiled shaders to the shader program glAttachShader(programId, vertexShaderId); glAttachShader(programId, fragmentShaderId);

glLinkProgram(programId); // links the shader program // check for linking errors glGetProgramiv(programId, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED " << infoLog << std::endl;

return false; }

glUseProgram(programId); // Uses the shader program

return true; }

void UDestroyShaderProgram(GLuint programId) { glDeleteProgram(programId); }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Mobile Communications

Authors: Jochen Schiller

2nd edition

978-0321123817, 321123816, 978-8131724262

More Books

Students also viewed these Programming questions