add initial shaders, draw using vertex attributes

This commit is contained in:
Josh Holtrop 2011-05-05 13:07:14 -04:00
parent f3d9a3b437
commit fb1d90e168
3 changed files with 176 additions and 17 deletions

31
f_shader.glsl Normal file
View File

@ -0,0 +1,31 @@
varying vec3 eye_pos_i;
varying vec3 normal_i;
varying vec4 diffuse_i;
void main(void)
{
vec3 n, lightDir;
vec4 color;
float NdotL, RdotEye;
lightDir = vec3(-0.1, 0, -0.9);
color = vec4(0.2, 0.2, 0.2, 1.0); /* ambient light */
n = normalize(normal_i);
NdotL = max(dot(n, -lightDir), 0.0);
if (NdotL > 0.0)
{
/* diffuse component */
color += diffuse_i * NdotL;
/* specular component */
RdotEye = dot(normalize(eye_pos_i), normalize(reflect(-lightDir, n)));
if (RdotEye > 0.0)
{
color += pow(RdotEye, 96.5);
}
}
gl_FragColor = color;
}

16
v_shader.glsl Normal file
View File

@ -0,0 +1,16 @@
attribute vec3 pos;
attribute vec3 color;
attribute vec3 normal;
varying vec3 eye_pos_i;
varying vec3 normal_i;
varying vec4 diffuse_i;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1);
eye_pos_i = vec3(gl_Position.x, gl_Position.y, gl_Position.z);
normal_i = gl_NormalMatrix * normal;
diffuse_i = vec4(color, 1);
}

View File

@ -1,5 +1,9 @@
/* Libraries we use */
#define GL_GLEXT_PROTOTYPES
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
@ -12,6 +16,11 @@ using namespace std;
#define HEIGHT 800
#define TITLE "Josh's Wavefront Object Viewer"
enum Locations {
LOC_POSITION,
LOC_NORMAL
};
class Viewer
{
public:
@ -30,8 +39,93 @@ private:
int m_startx, m_starty;
bool m_dragging;
float m_dist;
GLuint m_program, m_vs, m_fs;
};
char * loadFile(const char *fname)
{
struct stat st;
if (stat(fname, &st) != 0)
return NULL;
if (st.st_size <= 0)
return NULL;
char * buff = new char[st.st_size + 1];
int fd = open(fname, O_RDONLY);
read(fd, buff, st.st_size);
close(fd);
buff[st.st_size] = '\0';
return buff;
}
char *getShaderLog(GLuint id)
{
GLint log_length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char *log = new char[log_length];
glGetShaderInfoLog(id, log_length, &log_length, log);
return log;
}
return NULL;
}
char *getProgramLog(GLuint id)
{
GLint log_length;
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char *log = new char[log_length];
glGetProgramInfoLog(id, log_length, &log_length, log);
return log;
}
return NULL;
}
GLuint makeShader(GLenum shaderType, const char *fname)
{
GLuint id;
const char *source;
GLint status;
id = glCreateShader(shaderType);
if (id <= 0)
{
cerr << "Error creating shader object" << endl;
goto out;
}
source = loadFile(fname);
if (source == NULL)
{
fprintf(stderr, "Error reading file '%s'\n", fname);
goto cleanup_shader;
}
glShaderSource(id, 1, &source, NULL);
delete[] source;
glCompileShader(id);
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
cerr << "Error compiling shader" << endl;
char *log = getShaderLog(id);
cerr << "Shader Log:" << endl << log << endl;
delete[] log;
goto cleanup_shader;
}
return id;
cleanup_shader:
glDeleteShader(id);
out:
return 0;
}
/* The program's main entry point */
int main(int argc, char * argv[])
{
@ -75,6 +169,30 @@ Viewer::Viewer(const char * filename)
exit(1);
}
m_vs = makeShader(GL_VERTEX_SHADER, "v_shader.glsl");
m_fs = makeShader(GL_FRAGMENT_SHADER, "f_shader.glsl");
m_program = glCreateProgram();
glAttachShader(m_program, m_vs);
glAttachShader(m_program, m_fs);
glBindAttribLocation(m_program, LOC_POSITION, "pos");
glBindAttribLocation(m_program, LOC_NORMAL, "normal");
glLinkProgram(m_program);
GLint link_status;
glGetProgramiv(m_program, GL_LINK_STATUS, &link_status);
if (link_status != GL_TRUE)
{
char *log = getProgramLog(m_program);
cerr << "Program log:" << endl << log << endl;
delete[] log;
glDeleteShader(m_vs);
glDeleteShader(m_fs);
exit(1);
}
/* Print out the object's size */
const float * aabb = m_obj.getAABB();
cout << "Object width: " << (aabb[3]-aabb[0]) << endl;
@ -86,20 +204,10 @@ void Viewer::initgl()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glViewport(0, 0, WIDTH, HEIGHT);
setProjection();
glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix);
// float pos[] = {0.0, -1.0, 0.0, 0.0};
// glLightfv(GL_LIGHT0, GL_POSITION, pos);
GLfloat lightAmbient[] = {0.2, 0.2, 0.2, 1};
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
}
void Viewer::setProjection()
@ -117,18 +225,22 @@ void Viewer::display()
glLoadIdentity();
gluLookAt(0, -m_dist, 0, 0, 0, 0, 0, 0, 1);
glMultMatrixf(m_rotationMatrix);
m_obj.bindBuffers();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glUseProgram(m_program);
glEnableVertexAttribArray(LOC_POSITION);
glEnableVertexAttribArray(LOC_NORMAL);
int stride = m_obj.getStride();
glVertexPointer(3, GL_FLOAT, stride, (GLvoid *) m_obj.getVertexOffset());
glNormalPointer(GL_FLOAT, stride, (GLvoid *) m_obj.getNormalOffset());
glVertexAttribPointer(LOC_POSITION, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj.getVertexOffset());
glVertexAttribPointer(LOC_NORMAL, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj.getNormalOffset());
if (m_obj.doTextures())
{
glTexCoordPointer(2, GL_FLOAT, stride,
(GLvoid *) m_obj.getTextureCoordOffset());
/* TODO */
}
for (map<string, WFObj::Material>::iterator it = m_obj.getMaterials().begin();
for (map<string, WFObj::Material>::iterator it =
m_obj.getMaterials().begin();
it != m_obj.getMaterials().end();
it++)
{