Created
October 17, 2014 09:21
-
-
Save juriad/ba66f7184d12c5a29e84 to your computer and use it in GitHub Desktop.
Torus rendering
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Include standard headers | |
#include <stdio.h> | |
#include <stdlib.h> | |
// Include GLEW | |
#include <GL/glew.h> | |
// Include GLFW | |
#include <GLFW/glfw3.h> | |
GLFWwindow* window; | |
// Include GLM | |
#include <glm/glm.hpp> | |
#include <glm/gtc/matrix_transform.hpp> | |
using namespace glm; | |
#include "shader.hpp" | |
#include "texture.hpp" | |
int initWindow() { | |
// Initialise GLFW | |
if (!glfwInit()) { | |
fprintf( stderr, "Failed to initialize GLFW\n"); | |
return -1; | |
} | |
glfwWindowHint(GLFW_SAMPLES, 4); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | |
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |
// Open a window and create its OpenGL context | |
window = glfwCreateWindow(1024, 768, "Tutorial 05 - Textured Cube", NULL, | |
NULL); | |
if (window == NULL) { | |
fprintf( stderr, | |
"Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n"); | |
glfwTerminate(); | |
return -1; | |
} | |
glfwMakeContextCurrent(window); | |
// Initialize GLEW | |
glewExperimental = true; // Needed for core profile | |
if (glewInit() != GLEW_OK) { | |
fprintf(stderr, "Failed to initialize GLEW\n"); | |
return -1; | |
} | |
// Ensure we can capture the escape key being pressed below | |
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); | |
return 0; | |
} | |
void setCoords(double r, double c, int rSeg, int cSeg, int i, int j, | |
GLfloat * vertices, GLfloat * uv) { | |
const double PI = 3.1415926535897932384626433832795; | |
const double TAU = 2 * PI; | |
double x = (c + r * cos(i * TAU / rSeg)) * cos(j * TAU / cSeg); | |
double y = (c + r * cos(i * TAU / rSeg)) * sin(j * TAU / cSeg); | |
double z = r * sin(i * TAU / rSeg); | |
vertices[0] = 2 * x; | |
vertices[1] = 2 * y; | |
vertices[2] = 2 * z; | |
uv[0] = i / (double) rSeg; | |
uv[1] = j / (double) cSeg; | |
} | |
int createObject(double r, double c, int rSeg, int cSeg, GLfloat ** vertices, | |
GLfloat ** uv) { | |
int count = rSeg * cSeg * 6; | |
*vertices = (GLfloat *) malloc(count * 3 * sizeof(GLfloat)); | |
*uv = (GLfloat *) malloc(count * 2 * sizeof(GLfloat)); | |
for (int x = 0; x < cSeg; x++) { // through stripes | |
for (int y = 0; y < rSeg; y++) { // through squares on stripe | |
GLfloat * vertexPtr = *vertices + ((x * rSeg) + y) * 18; | |
GLfloat * uvPtr = *uv + ((x * rSeg) + y) * 12; | |
setCoords(r, c, rSeg, cSeg, x, y, vertexPtr + 0, uvPtr + 0); | |
setCoords(r, c, rSeg, cSeg, x + 1, y, vertexPtr + 3, uvPtr + 2); | |
setCoords(r, c, rSeg, cSeg, x, y + 1, vertexPtr + 6, uvPtr + 4); | |
setCoords(r, c, rSeg, cSeg, x, y + 1, vertexPtr + 9, uvPtr + 6); | |
setCoords(r, c, rSeg, cSeg, x + 1, y, vertexPtr + 12, uvPtr + 8); | |
setCoords(r, c, rSeg, cSeg, x + 1, y + 1, vertexPtr + 15, | |
uvPtr + 10); | |
} | |
} | |
return count; | |
} | |
int main(void) { | |
if (initWindow() != 0) { | |
return -1; | |
} | |
// Dark blue background | |
glClearColor(0.0f, 0.0f, 0.4f, 0.0f); | |
glDisable(GL_CULL_FACE); | |
// Enable depth test | |
glEnable(GL_DEPTH_TEST); | |
// Accept fragment if it closer to the camera than the former one | |
glDepthFunc(GL_LESS); | |
GLuint VertexArrayID; | |
glGenVertexArrays(1, &VertexArrayID); | |
glBindVertexArray(VertexArrayID); | |
// Create and compile our GLSL program from the shaders | |
GLuint programID = LoadShaders("TransformVertexShader.vertexshader", | |
"TextureFragmentShader.fragmentshader"); | |
// Get a handle for our "MVP" uniform | |
GLuint MatrixID = glGetUniformLocation(programID, "MVP"); | |
// Projection matrix : 45� Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units | |
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f); | |
// Camera matrix | |
glm::mat4 View = glm::lookAt(glm::vec3(0, -15, 12), // Camera is at (4,3,3), in World Space | |
glm::vec3(0, 0, 0), // and looks at the origin | |
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down) | |
); | |
// Model matrix : an identity matrix (model will be at the origin) | |
glm::mat4 Model = glm::mat4(1.0f); | |
// Our ModelViewProjection : multiplication of our 3 matrices | |
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around | |
// Load the texture using any two methods | |
GLuint Texture = loadBMP_custom("uvtemplate1.bmp"); | |
//GLuint Texture = loadDDS("uvtemplate.DDS"); | |
// Get a handle for our "myTextureSampler" uniform | |
GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler"); | |
GLfloat * g_vertex_buffer_data; | |
GLfloat * g_uv_buffer_data; | |
int vertices = createObject(1, 2, 360, 360, &g_vertex_buffer_data, | |
&g_uv_buffer_data); | |
GLuint vertexbuffer; | |
glGenBuffers(1, &vertexbuffer); | |
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); | |
glBufferData(GL_ARRAY_BUFFER, vertices * 3 * sizeof(GLfloat), | |
g_vertex_buffer_data, GL_STATIC_DRAW); | |
GLuint uvbuffer; | |
glGenBuffers(1, &uvbuffer); | |
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); | |
glBufferData(GL_ARRAY_BUFFER, vertices * 2 * sizeof(GLfloat), | |
g_uv_buffer_data, GL_STATIC_DRAW); | |
do { | |
// Clear the screen | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE); | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
glEnable(GL_DEPTH_TEST); | |
glDepthMask(GL_TRUE); | |
glDepthFunc(GL_LEQUAL); | |
glDepthRange(0.0f, 1.0f); | |
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | |
glClearDepth(1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
// Use our shader | |
glUseProgram(programID); | |
// Send our transformation to the currently bound shader, | |
// in the "MVP" uniform | |
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]); | |
// Bind our texture in Texture Unit 0 | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, Texture); | |
// Set our "myTextureSampler" sampler to user Texture Unit 0 | |
glUniform1i(TextureID, 0); | |
// 1rst attribute buffer : vertices | |
glEnableVertexAttribArray(0); | |
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); | |
glVertexAttribPointer(0, // attribute. No particular reason for 0, but must match the layout in the shader. | |
3, // size | |
GL_FLOAT, // type | |
GL_FALSE, // normalized? | |
0, // stride | |
(void*) 0 // array buffer offset | |
); | |
// 2nd attribute buffer : UVs | |
glEnableVertexAttribArray(1); | |
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); | |
glVertexAttribPointer(1, // attribute. No particular reason for 1, but must match the layout in the shader. | |
2, // size : U+V => 2 | |
GL_FLOAT, // type | |
GL_FALSE, // normalized? | |
0, // stride | |
(void*) 0 // array buffer offset | |
); | |
glFrontFace(GL_CW); | |
// Draw the triangle ! | |
glDrawArrays(GL_TRIANGLES, 0, vertices * 3); // 12*3 indices starting at 0 -> 12 triangles | |
glFrontFace(GL_CCW); | |
glDisableVertexAttribArray(0); | |
glDisableVertexAttribArray(1); | |
// Swap buffers | |
glfwSwapBuffers(window); | |
glfwPollEvents(); | |
} // Check if the ESC key was pressed or the window was closed | |
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS | |
&& glfwWindowShouldClose(window) == 0); | |
// Cleanup VBO and shader | |
glDeleteBuffers(1, &vertexbuffer); | |
glDeleteBuffers(1, &uvbuffer); | |
glDeleteProgram(programID); | |
glDeleteTextures(1, &TextureID); | |
glDeleteVertexArrays(1, &VertexArrayID); | |
// Close OpenGL window and terminate GLFW | |
glfwTerminate(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment