Skip to content

Commit

Permalink
Hello sprite
Browse files Browse the repository at this point in the history
  • Loading branch information
m-decoster committed Jun 11, 2015
1 parent 721a559 commit 8316188
Show file tree
Hide file tree
Showing 9 changed files with 652 additions and 2 deletions.
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
CC=g++
CFLAGS=-Wall
INCLUDES=-Isrc/libs/
LIBS=-Llib -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo
LIBS=-Llib -lglfw3 -lSOIL -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo

all: hello_triangle hello_sprite

hello_triangle:
$(CC) $(INCLUDES) $(CFLAGS) src/examples/01-hello_triangle/main.cpp src/examples/common/util.cpp src/examples/common/shader.cpp -o bin/01-hello_triangle.out $(LIBS)

hello_sprite:
$(CC) $(INCLUDES) $(CFLAGS) src/examples/02-hello_sprite/main.cpp src/examples/common/util.cpp src/examples/common/shader.cpp -o bin/02-hello_sprite.out $(LIBS)
cp src/examples/02-hello_sprite/image.png bin/image.png

clean:
rm bin/*
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ that compiles and runs on your machine.
These examples have some dependencies:

* [GLFW 3.1.1](http://www.glfw.org)
* [SOIL](http://www.lonesock.net/soil.html)

## Compiling

Expand All @@ -26,6 +27,12 @@ Make sure that you have compiled the GLFW dependency for your system as a
static library. You should now have a file called `libglfw3.a`. Place this
in a subdirectory `lib` of the root folder (on the same level as this `README.md` file).

Download the latest release of SOIL. You can try putting the binary in the `lib` folder, but this
will most likely fail if your computer is from the last few years. You're best off using the supplied
makefile in the `projects/makefile` folder. Note that you need to alter a line if your machine is 64 bit:
change the line that says `CXX = gcc` to `CXX = gcc -arch x86_64`. Run `make` and you will find the new
`libSOIL.a` file in the `lib` subdirectory of the directory where you downloaded SOIL to.

Now you can use the command `make EXAMPLE_NAME` to compile an example. The
resulting binaries will be placed in the `build` folder.

Expand All @@ -37,13 +44,27 @@ domain is not recognized in every country. For more information, read

## Examples

To compile all examples, you can run `make` or `make all`.

### 01: Hello Triangle

**Compile**: `make hello_triangle`
**Run**: `bin/01-hello-triangle.out`
**Run**: `cd bin; 01-hello-triangle.out`

This example shows the minimal code needed to render a simple colored triangle.

[Code](src/examples/01-hello_triangle)

![hello triangle](img/01-hello_triangle.tiff)

### 02: Hello Sprite

**Compile**: `make hello_sprite`
**Run**: `cd bin; 02-hello_sprite.out`

This example shows the minimal code needed to render a textured quad. It also uses
`glDrawElements` to reduce duplication of vertices.

[Code](src/examples/02-hello_sprite)

![hello sprite](img/02-hello_sprite.tiff)
Binary file added bin/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/02-hello_sprite.tiff
Binary file not shown.
Binary file added src/examples/02-hello_sprite/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
162 changes: 162 additions & 0 deletions src/examples/02-hello_sprite/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include "../common/util.h"
#include "../common/shader.h"

const char* VERTEX_SRC = "#version 330 core\n"
"layout(location=0) in vec2 position;" // Vertex position (x, y)
"layout(location=1) in vec3 color;" // Vertex color (r, g, b)
"layout(location=2) in vec2 texcoord;" // Texture coordinate (u, v)
"out vec3 fColor;" // Vertex shader has to pass color to fragment shader
"out vec2 fTexcoord;" // Pass to fragment shader
"void main()"
"{"
" fColor = color;" // Pass color to fragment shader
" fTexcoord = texcoord;" // Pass texcoord to fragment shader
" gl_Position=vec4(position, 0.0, 1.0);" // Place vertex at (x, y, 0, 1)
"}";

const char* FRAGMENT_SRC = "#version 330 core\n"
"in vec3 fColor;" // From the vertex shader
"in vec2 fTexcoord;" // From the vertex shader
"uniform sampler2D tex;" // The texture
"out vec4 outputColor;" // The color of the resulting fragment
"void main()"
"{"
" outputColor = texture(tex, fTexcoord)" // Color using the color and texutre
" * vec4(fColor, 1.0);"
"}";

int main(void)
{
GLFWwindow* window;

// The OpenGL context creation code is in
// ../common/util.cpp
window = init("Hello Sprite", 640, 480);
if(!window)
{
return -1;
}

// We start by creating a vertex and fragment shader
// from the above strings
GLuint vertex = createShader(VERTEX_SRC, GL_VERTEX_SHADER);
if(!vertex)
{
return -1;
}
GLuint fragment = createShader(FRAGMENT_SRC, GL_FRAGMENT_SHADER);
if(!fragment)
{
return -1;
}
// Now we must make a shader program: this program
// contains both the vertex and the fragment shader
GLuint program = createShaderProgram(vertex, fragment);
if(!program)
{
return -1;
}
// We link the program, just like your C compiler links
// .o files
bool result = linkShader(program);
if(!result)
{
return -1;
}
// We make sure the shader is validated
result = validateShader(program);
if(!result)
{
return -1;
}
// Detach and delete the shaders, because we no longer need them
glDetachShader(program, vertex);
glDeleteShader(vertex);
glDetachShader(program, fragment);
glDeleteShader(fragment);

glUseProgram(program); // Set this as the current shader program

// We now create the data to send to the GPU
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

GLuint vbo;
glGenBuffers(1, &vbo);

float vertices[] =
{
// x y r g b u v
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};

// Upload the vertices to the buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

GLuint ebo;
glGenBuffers(1, &ebo);

GLuint indices[] =
{
0, 1, 2,
2, 3, 0
};

// Upload the indices (elements) to the buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// Enable the vertex attributes and upload their data (see: layout(location=x))
glEnableVertexAttribArray(0); // position
// 2 floats: x and y, but 7 floats in total per row
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(1); // color
// 3 floats: r, g and b, but 7 floats in total per row and start at the third one
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); // texture coordinates
// 2 floats: u and v, but 7 floats in total per row and start at the sixth one
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(5 * sizeof(GLfloat)));

// We have now successfully created a drawable Vertex Array Object

// Load the texture and bind it to the uniform
int w, h;
GLuint texture = loadImage("image.png", &w, &h, 0); // GL_TEXTURE0
if(!texture)
{
return -1;
}
glUniform1i(glGetUniformLocation(program, "tex"), 0); // GL_TEXTURE0

// Set the clear color to a light grey
glClearColor(0.75f, 0.75f, 0.75f, 1.0f);

while(!glfwWindowShouldClose(window))
{
// Clear
glClear(GL_COLOR_BUFFER_BIT);

// The VAO is still bound so just draw the 6 vertices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

// Tip: if nothing is drawn, check the return value of glGetError and google it

// Swap buffers to show current image on screen (for more information google 'backbuffer')
glfwSwapBuffers(window);
glfwPollEvents();
}

// Clean up
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteVertexArrays(1, &vao);
glDeleteTextures(1, &texture);

glfwTerminate();
return 0;
}
25 changes: 25 additions & 0 deletions src/examples/common/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,30 @@ GLFWwindow* init(const char* exampleName, int width, int height)

std::cout << "Using OpenGL version " << glGetString(GL_VERSION) << std::endl;

glEnable(GL_TEXTURE_2D);

return window;
}

GLuint loadImage(const char* fileName, int* w, int* h, int index)
{
GLuint tex;
unsigned char* img = SOIL_load_image(fileName, w, h, NULL, SOIL_LOAD_RGB);
if(!img)
{
std::cerr << "Error loading image " << fileName << ": " << SOIL_last_result() << std::endl;
return 0;
}

glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0 + index);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, *w, *h, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
SOIL_free_image_data(img);

return tex;
}
3 changes: 3 additions & 0 deletions src/examples/common/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#define GLFW_INCLUDE_GLCOREARB // Needed for OpenGL 3.3 on OS X
#include <GLFW/glfw3.h>

#include <SOIL/SOIL.h>

#include <cstdlib>
#include <iostream>

GLFWwindow* init(const char* exampleName, int width, int height);
GLuint loadImage(const char* fileName, int* w, int* h, int index);

#endif
Loading

0 comments on commit 8316188

Please sign in to comment.