图形学实验报告

发布时间:2015-05-05 22:46:57

实验 基于着色器的纹理映射与光照渲染

一、 实验内容

在实验三的基础上,增加如下功能:

1、 绘制一个由细分四面体得到的三维镂垫(或三维迷宫)及其适当的场景(任选);

2、 在场景中至少添加三个光源:一个平行光、一个点光源、一个聚光灯;

3、 给三维镂垫表面(或三维迷宫)添加适当的纹理;

4、 可通过鼠标或键盘的按键(包括特殊健、组合健等)、菜单、滑动条等工具来实现光源、材质属性参数的设置,也包括对光源位置的控制等。

二、 实验环境

VS2012

三、 实验方案与程序设计

主程序(Exe4:

#pragma comment(lib, "glew32.lib")

#include "Angel.h"

static bool flag1 = true;

static bool flag2 = true;

const int NumTimesToSubdivide = 5;

const int NumTetrahedrons = 1024;

const int NumTriangles = 4*NumTetrahedrons;

const int NumVertices = 3 * NumTriangles;

const int TextureSize = 64;

typedef Angel::vec4 point4;

typedef Angel::vec4 color4;

GLuint textures[2];

GLubyte image[TextureSize][TextureSize][3];

GLubyte image2[TextureSize][TextureSize][3];

point4 points[NumVertices];

vec3 normals[NumVertices];

vec2 tex_coords[NumVertices];

GLuint ModelView, Projection, LightPosition;

//GLuint LightPosition;

float a = 0.0, b = 0.0, c = 2.0;

static GLfloat light_position[] = { a, b, c, 0.0 };

int Index = 0;

GLfloat x = 0.0;

GLfloat y = 0.0;

GLfloat z = 1.0;;

GLfloat LeftOrRight = 0.0;

GLfloat UpOrDown = 0.0;

void

draw( const vec3& a, const vec3& b, const vec3& c )

{

vec3 normal = normalize( cross(b - a, c - b) );

normals[Index] = normal; points[Index] = a; tex_coords[Index] = vec2( 0.0, 0.0 ); Index++;

normals[Index] = normal; points[Index] = b; tex_coords[Index] = vec2( 0.0, 1.0 ); Index++;

normals[Index] = normal; points[Index] = c; tex_coords[Index] = vec2( 1.0, 1.0 ); Index++;

}

void

tetra( const vec3& a, const vec3& b, const vec3& c, const vec3& d )

{

draw( a, b, c );

draw( a, c, d );

draw( a, d, b );

draw( b, d, c );

}

void

divide_tetra( const vec3& a, const vec3& b,

const vec3& c, const vec3& d, int count )

{

if ( count > 0 ) {

vec3 v0 = ( a + b ) / 2.0;

vec3 v1 = ( a + c ) / 2.0;

vec3 v2 = ( a + d ) / 2.0;

vec3 v3 = ( b + c ) / 2.0;

vec3 v4 = ( c + d ) / 2.0;

vec3 v5 = ( b + d ) / 2.0;

divide_tetra( a, v0, v1, v2, count - 1 );

divide_tetra( v0, b, v3, v5, count - 1 );

divide_tetra( v1, v3, c, v4, count - 1 );

divide_tetra( v2, v4, d, v5, count - 1 );

}

else {

tetra( a, b, c, d );

}

}

void

init(void)

{

vec3 vertices[4] = {

vec3( 0.0, 0.0, 1.0 ),

vec3( 0.0, 0.942809, -0.333333 ),

vec3( -0.816497, -0.471405, -0.333333 ),

vec3( 0.816497, -0.471405, -0.333333 )

};

divide_tetra( vertices[0], vertices[1], vertices[2], vertices[3],

NumTimesToSubdivide );

for ( int i = 0; i < 64; i++ ) {

for ( int j = 0; j < 64; j++ ) {

GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;

image[i][j][0] = c;

image[i][j][1] = c;

image[i][j][2] = c;

image2[i][j][0] = c;

image2[i][j][1] = 0;

image2[i][j][2] = c;

}

}

glGenTextures( 2, textures );

glBindTexture( GL_TEXTURE_2D, textures[0] );

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,

GL_RGB, GL_UNSIGNED_BYTE, image );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

glBindTexture( GL_TEXTURE_2D, textures[1] );

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,

GL_RGB, GL_UNSIGNED_BYTE, image2 );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

glActiveTexture( GL_TEXTURE0 );

glBindTexture( GL_TEXTURE_2D, textures[0] );

GLuint vao;

glGenVertexs( 1, &vao );

glBindVertex( vao );

GLuint buffer;

glGenBuffers( 1, &buffer );

glBindBuffer( GL_ARRAY_BUFFER, buffer );

glBufferData( GL_ARRAY_BUFFER, sizeof(points) + sizeof(normals)+ sizeof(tex_coords),

NULL, GL_STATIC_DRAW );

GLintptr offset = 0;

glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );

offset += sizeof(points);

glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(normals), normals );

offset += sizeof(normals);

glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );

GLuint program = InitShader( "vshader4.glsl", "fshader4.glsl" );

glUseProgram( program );

offset = 0;

GLuint vPosition = glGetAttribLocation( program, "vPosition" );

glEnableVertexAttrib( vPosition );

glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,

BUFFER_OFFSET(offset) );

offset += sizeof(points);

GLuint vNormal = glGetAttribLocation( program, "vNormal" );

glEnableVertexAttrib( vNormal );

glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0,

BUFFER_OFFSET(offset) );

offset += sizeof(normals);

GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );

glEnableVertexAttrib( vTexCoord );

glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,

BUFFER_OFFSET(offset) );

glUniform1i( glGetUniformLocation(program, "texture"), 0 );

color4 light_ambient( 0.2, 0.2, 0.2, 1.0 );

color4 light_diffuse( 1.0, 1.0, 1.0, 1.0 );

color4 light_specular( 1.0, 1.0, 1.0, 1.0 );

color4 material_ambient( 1.0, 0.0, 1.0, 1.0 );

color4 material_diffuse( 1.0, 0.8, 0.0, 1.0 );

color4 material_specular( 1.0, 0.0, 1.0, 1.0 );

float material_shininess = 5.0;

color4 ambient_product = light_ambient * material_ambient;

color4 diffuse_product = light_diffuse * material_diffuse;

color4 specular_product = light_specular * material_specular;

glUniform4fv( glGetUniformLocation(program, "AmbientProduct"),

1, ambient_product );

glUniform4fv( glGetUniformLocation(program, "DiffuseProduct"),

1, diffuse_product );

glUniform4fv( glGetUniformLocation(program, "SpecularProduct"),

1, specular_product );

// glUniform4fv( glGetUniformLocation(program, "LightPosition"),

// 1, light_position );

glUniform1f( glGetUniformLocation(program, "Shininess"),

material_shininess );

ModelView = glGetUniformLocation( program, "ModelView" );

Projection = glGetUniformLocation( program, "Projection" );

LightPosition = glGetUniformLocation( program, "LightPosition" );

glUniform4fv( LightPosition ,1,light_position);

glEnable( GL_DEPTH_TEST );

glClearColor( 1.0, 1.0, 1.0, 1.0 );

}

void

display( void )

{

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

point4 eye( x,y,z,1.0 );

point4 at( LeftOrRight, UpOrDown, 0.0, 1.0 );

vec4 up( 0.0, 1.0, 0.0, 0.0 );

mat4 model_view = LookAt( eye, at, up );

glUniformMatrix4fv( ModelView, 1, GL_TRUE, model_view );

mat4 p = Ortho( -1.0, 2.5, -1.0, 2.5, 1.0, 100);

glUniformMatrix4fv( Projection, 1, GL_TRUE, p );

glDraws( GL_TRIANGLES, 0, NumVertices );

glutSwapBuffers();

}

void

keyboard( unsigned char key, int MM, int VB )

{

if(key == 'q' || key == 'Q') exit( EXIT_SUCCESS );

//漫游

if(key == 'D' || key == 'd') LeftOrRight += 0.1;

if(key == 'A' || key == 'a') LeftOrRight -= 0.1;

if(key == 'W' || key == 'w') UpOrDown += 0.1;

if(key == 'S' || key == 's') UpOrDown -= 0.1;

//环视

if(key == 'J' || key == 'j'){

// if(y>1.0) y =0;

y += 0.1;

}

if(key == 'K' || key == 'k'){

y -= 0.1;

}

if(key == 'U' || key == 'u'){

//if(z>=0.7)

z -= 0.1;

}

if(key == 'I' || key == 'i'){

z += 0.1;

}

if(key == 'N' || key == 'n'){

x -= 0.1;

}

if(key == 'M' || key == 'm'){

x += 0.1;

}

if(key == 'B' || key == 'b')

{

LeftOrRight = 0.0;

UpOrDown = 0.0;

x = 0.0;

y = 0.0;

z = 1.0;

//light_position( 0.0, 0.0, 2.0, 0.0 );

light_position[0] = a;

light_position[1] = b;

light_position[2] = c;

glUniform4fv( LightPosition ,1,light_position);

}

if(key =='1'){

flag1 = !flag1;

if(flag1){

glBindTexture( GL_TEXTURE_2D, textures[0] );

}

else{

glBindTexture( GL_TEXTURE_2D, textures[1] );

}

}

glutPostRedisplay();

}

void special(int key,int x,int y){

if(key == GLUT_KEY_SHIFT_L){

flag2 = !flag2;

}

}

void mouse(int key,int state,int x,int y){

glEnable(GL_LIGHTING);

if(key == GLUT_LEFT_BUTTON && state == GLUT_DOWN){

if(flag2){

light_position[0]++;

}

else{

light_position[0]--;

}

}

if(key == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN){

if(flag2){

light_position[1]++;

}

else{

light_position[1]--;

}

}

if(key == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){

if(flag2){

light_position[2]++;

}

else{

light_position[2]--;

}

}

glUniform4fv( LightPosition ,1,light_position);

glutPostRedisplay();

}

void

reshape( int width, int height )

{

glViewport( 0, 0, width, height );

GLfloat left = -2.0, right = 2.0;

GLfloat top = 2.0, bottom = -2.0;

GLfloat zNear = -20.0, zFar = 20.0;

GLfloat aspect = GLfloat(width)/height;

if ( aspect > 1.0 ) {

left *= aspect;

right *= aspect;

}

else {

top /= aspect;

bottom /= aspect;

}

mat4 projection = Ortho( left, right, bottom, top, zNear, zFar );

glUniformMatrix4fv( Projection, 1, GL_TRUE, projection );

}

int

main( int argc, char **argv )

{

glutInit( &argc, argv );

glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH );

glutInitWindowSize( 640, 640 );

glutInitContextVersion( 3, 2 );

glutInitContextProfile( GLUT_CORE_PROFILE );

glutCreateWindow( "Exe4" );

glewExperimental = true;

glewInit();

init();

glutDisplayFunc( display );

glutReshapeFunc( reshape );

glutKeyboardFunc( keyboard );

glutSpecialFunc(special);

glutMouseFunc(mouse);

glutMainLoop();

return 0;

}

片元着色器(fshader:

#version 150

// per-fragment interpolated values from the vertex shader

in vec3 fN;

in vec3 fL;

in vec3 fE;

in vec4 color;

in vec2 texCoord;

out vec4 fColor;

uniform vec4 AmbientProduct, DiffuseProduct, SpecularProduct;

uniform mat4 ModelView;

uniform vec4 LightPosition;

uniform float Shininess;

uniform sampler2D texture;

void main()

{

// Normalize the input lighting vectors

vec3 N = normalize(fN);

vec3 E = normalize(fE);

vec3 L = normalize(fL);

vec3 H = normalize( L + E );

vec4 ambient = AmbientProduct;

float Kd = max(dot(L, N), 0.0);

vec4 diffuse = Kd*DiffuseProduct;

float Ks = pow(max(dot(N, H), 0.0), Shininess);

vec4 specular = Ks*SpecularProduct;

// discard the specular highlight if the light's behind the vertex

if( dot(L, N) < 0.0 ) {

specular = vec4(0.0, 0.0, 0.0, 1.0);

}

fColor = ambient + diffuse + specular;

fColor.a = 1.0;

fColor += color * texture2D( texture, texCoord );

}

顶点着色器(vshader:

#version 150

in vec4 vPosition;

in vec3 vNormal;

in vec4 vColor;

in vec2 vTexCoord;

// output values that will be interpretated per-fragment

out vec3 fN;

out vec3 fE;

out vec3 fL;

out vec4 color;

out vec2 texCoord;

uniform mat4 ModelView;

uniform vec4 LightPosition;

uniform mat4 Projection;

void main()

{

fN = vNormal;

fE = vPosition.xyz;

fL = LightPosition.xyz;

if( LightPosition.w != 0.0 ) {

fL = LightPosition.xyz - vPosition.xyz;

}

color = vColor;

texCoord = vTexCoord;

gl_Position = Projection*ModelView*vPosition;

}

四、 实验结果与分析(包括功能说明、操作说明)

实现功能:

绘制一个由细分四面体得到的三维镂垫;

光源: 在场景中添加一个点光源;通过鼠标点击左键,中间和右键来改变光源位置,左SHIFT可以切换点击时如何改变,相当于有6个改变光源位置的不同按键。

纹理:按键‘1’用来切换两种不同的纹理类型;似乎是光照的影响,纹理的效 果不能明显的看出来

摄像漫游:通过键盘WSAD键来前后左右地移动摄像机;

摄像机环视:UI,JKNM键旋转摄像机环顾四周;

按键B进行初始化,按键Q退出程序。

五、 实验心得(自我评价)与建议

通过此次实验,我对OPENGL的光照模型和纹理映射有了一定的了解,在实现修改光源位置功能的时候遇到了很多困难,虽然最后解决了问题,还是有一些不足,同时对于纹理映射明白得不够透彻,在今后的学习中,我将继续深入探讨OPENGL的奥秘。

图形学实验报告

相关推荐