191 строка
6.5 KiB
C
191 строка
6.5 KiB
C
|
/*******************************************************************
|
||
|
* *
|
||
|
* Using SDL With OpenGL *
|
||
|
* *
|
||
|
* Tutorial by Kyle Foley (sdw) *
|
||
|
* *
|
||
|
* http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
|
||
|
* *
|
||
|
*******************************************************************/
|
||
|
|
||
|
/*
|
||
|
Combined with opengl.org tutorial #2,
|
||
|
http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29
|
||
|
*/
|
||
|
|
||
|
#include "SDL/SDL.h"
|
||
|
#include "SDL/SDL_opengl.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
char* filetobuf(char *file)
|
||
|
{
|
||
|
FILE *fptr;
|
||
|
long length;
|
||
|
char *buf;
|
||
|
|
||
|
fptr = fopen(file, "r"); /* Open file for reading */
|
||
|
if (!fptr) /* Return NULL on failure */
|
||
|
return NULL;
|
||
|
fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */
|
||
|
length = ftell(fptr); /* Find out how many bytes into the file we are */
|
||
|
buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */
|
||
|
fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */
|
||
|
fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */
|
||
|
fclose(fptr); /* Close the file */
|
||
|
buf[length] = 0; /* Null terminator */
|
||
|
|
||
|
return buf; /* Return the buffer */
|
||
|
}
|
||
|
|
||
|
void drawscene()
|
||
|
{
|
||
|
int i; /* Simple iterator */
|
||
|
GLuint vao, vbo[2]; /* Create handles for our Vertex Array Object and two Vertex Buffer Objects */
|
||
|
|
||
|
/* We're going to create a simple diamond made from lines */
|
||
|
const GLfloat diamond[4][2] = {
|
||
|
{ 0.0, 1.0 }, /* Top point */
|
||
|
{ 1.0, 0.0 }, /* Right point */
|
||
|
{ 0.0, -1.0 }, /* Bottom point */
|
||
|
{ -1.0, 0.0 } }; /* Left point */
|
||
|
|
||
|
const GLfloat colors[4][3] = {
|
||
|
{ 1.0, 0.0, 0.0 }, /* Red */
|
||
|
{ 0.0, 1.0, 0.0 }, /* Green */
|
||
|
{ 0.0, 0.0, 1.0 }, /* Blue */
|
||
|
{ 1.0, 1.0, 1.0 } }; /* White */
|
||
|
|
||
|
/* These pointers will receive the contents of our shader source code files */
|
||
|
GLchar *vertexsource, *fragmentsource;
|
||
|
|
||
|
/* These are handles used to reference the shaders */
|
||
|
GLuint vertexshader, fragmentshader;
|
||
|
|
||
|
/* This is a handle to the shader program */
|
||
|
GLuint shaderprogram;
|
||
|
|
||
|
/* Allocate and assign a Vertex Array Object to our handle */
|
||
|
glGenVertexArrays(1, &vao);
|
||
|
|
||
|
/* Bind our Vertex Array Object as the current used object */
|
||
|
glBindVertexArray(vao);
|
||
|
|
||
|
/* Allocate and assign two Vertex Buffer Objects to our handle */
|
||
|
glGenBuffers(2, vbo);
|
||
|
|
||
|
/* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */
|
||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
|
||
|
|
||
|
/* Copy the vertex data from diamond to our buffer */
|
||
|
/* 8 * sizeof(GLfloat) is the size of the diamond array, since it contains 8 GLfloat values */
|
||
|
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW);
|
||
|
|
||
|
/* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */
|
||
|
glVertexAttribPointer((GLuint)0, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||
|
|
||
|
/* Enable attribute index 0 as being used */
|
||
|
glEnableVertexAttribArray(0);
|
||
|
|
||
|
/* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */
|
||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
|
||
|
|
||
|
/* Copy the color data from colors to our buffer */
|
||
|
/* 12 * sizeof(GLfloat) is the size of the colors array, since it contains 12 GLfloat values */
|
||
|
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
|
||
|
|
||
|
/* Specify that our color data is going into attribute index 1, and contains three floats per vertex */
|
||
|
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||
|
|
||
|
/* Enable attribute index 1 as being used */
|
||
|
glEnableVertexAttribArray(1);
|
||
|
|
||
|
/* Read our shaders into the appropriate buffers */
|
||
|
vertexsource = filetobuf("tutorial2.vert");
|
||
|
fragmentsource = filetobuf("tutorial2.frag");
|
||
|
|
||
|
/* Assign our handles a "name" to new shader objects */
|
||
|
vertexshader = glCreateShader(GL_VERTEX_SHADER);
|
||
|
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
|
||
|
|
||
|
/* Associate the source code buffers with each handle */
|
||
|
glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);
|
||
|
glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);
|
||
|
|
||
|
/* Compile our shader objects */
|
||
|
glCompileShader(vertexshader);
|
||
|
glCompileShader(fragmentshader);
|
||
|
|
||
|
/* Assign our program handle a "name" */
|
||
|
shaderprogram = glCreateProgram();
|
||
|
|
||
|
/* Attach our shaders to our program */
|
||
|
glAttachShader(shaderprogram, vertexshader);
|
||
|
glAttachShader(shaderprogram, fragmentshader);
|
||
|
|
||
|
/* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */
|
||
|
glBindAttribLocation(shaderprogram, 0, "in_Position");
|
||
|
glBindAttribLocation(shaderprogram, 1, "in_Color");
|
||
|
|
||
|
/* Link our program, and set it as being actively used */
|
||
|
glLinkProgram(shaderprogram);
|
||
|
glUseProgram(shaderprogram);
|
||
|
|
||
|
/* Loop our display increasing the number of shown vertexes each time.
|
||
|
* Start with 2 vertexes (a line) and increase to 3 (a triangle) and 4 (a diamond) */
|
||
|
for (i=4; i <= 4; i++)
|
||
|
{
|
||
|
/* Make our background black */
|
||
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
|
||
|
/* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */
|
||
|
glDrawArrays(GL_LINE_LOOP, 0, i);
|
||
|
|
||
|
/* Swap our buffers to make our changes visible */
|
||
|
SDL_GL_SwapBuffers();
|
||
|
|
||
|
/* Sleep for 2 seconds */
|
||
|
SDL_Delay(2000);
|
||
|
}
|
||
|
|
||
|
/* Cleanup all the things we bound and allocated */
|
||
|
glUseProgram(0);
|
||
|
glDisableVertexAttribArray(0);
|
||
|
glDisableVertexAttribArray(1);
|
||
|
glDetachShader(shaderprogram, vertexshader);
|
||
|
glDetachShader(shaderprogram, fragmentshader);
|
||
|
glDeleteProgram(shaderprogram);
|
||
|
glDeleteShader(vertexshader);
|
||
|
glDeleteShader(fragmentshader);
|
||
|
glDeleteBuffers(2, vbo);
|
||
|
glDeleteVertexArrays(1, &vao);
|
||
|
free(vertexsource);
|
||
|
free(fragmentsource);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
SDL_Surface *screen;
|
||
|
|
||
|
// Slightly different SDL initialization
|
||
|
if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
|
||
|
printf("Unable to initialize SDL: %s\n", SDL_GetError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
|
||
|
|
||
|
screen = SDL_SetVideoMode( 512, 384, 32, SDL_OPENGL); // *changed*
|
||
|
if ( !screen ) {
|
||
|
printf("Unable to set video mode: %s\n", SDL_GetError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
drawscene();
|
||
|
|
||
|
SDL_Quit();
|
||
|
|
||
|
return 0;
|
||
|
}
|