简单的光照checkerboard球体shader实现

本文详细介绍了使用OpenGL进行三维立体方块的绘制,并通过光线追踪实现逼真的光照效果,包括光源设置、物体表面材质的计算及最终的渲染呈现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenGL程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gl\glew.h>
#include <gl\glut.h>

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

float window_width=600;
float window_height=600;

GLfloat xRot = 0.0f;
GLfloat yRot = 0.0f;
GLfloat xTrans = 0;
GLfloat yTrans = 0;
GLfloat zTrans = -32.0;

int ox;
int oy;
int buttonState;
GLfloat xRotLength = 0.0f;
GLfloat yRotLength = 0.0f;

GLfloat LightAmbient[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 20.0f, 20.0f, 20.0f, 1.0f };

GLuint f;
GLuint v;
GLuint p;

void draw_box(float ox, float oy, float oz, float width, float height, float length)
{
    glLineWidth(1.0f);

    glBegin(GL_LINES);   
        glColor3f(1.0f, 0.0f, 0.0f);
//1
        glVertex3f(ox, oy, oz);
        glVertex3f(ox+width, oy, oz);

//2
        glVertex3f(ox, oy, oz);
        glVertex3f(ox, oy+height, oz);

//3
        glVertex3f(ox, oy, oz);
        glVertex3f(ox, oy, oz+length);

//4
        glVertex3f(ox+width, oy, oz);
        glVertex3f(ox+width, oy+height, oz);

//5
        glVertex3f(ox+width, oy+height, oz);
        glVertex3f(ox, oy+height, oz);

//6
        glVertex3f(ox, oy+height, oz+length);
        glVertex3f(ox, oy, oz+length);

//7
        glVertex3f(ox, oy+height, oz+length);
        glVertex3f(ox, oy+height, oz);

//8
        glVertex3f(ox+width, oy, oz);
        glVertex3f(ox+width, oy, oz+length);

//9
        glVertex3f(ox, oy, oz+length);
        glVertex3f(ox+width, oy, oz+length);

//10
        glVertex3f(ox+width, oy+height, oz);
        glVertex3f(ox+width, oy+height, oz+length);

//11
        glVertex3f(ox+width, oy+height, oz+length);
        glVertex3f(ox+width, oy, oz+length);

//12
        glVertex3f(ox, oy+height, oz+length);
        glVertex3f(ox+width, oy+height, oz+length);
    glEnd();
}

void set_shaders()
{
char *vs=NULL;
char *fs=NULL;

vs=(char *)malloc(sizeof(char)*10000);
fs=(char *)malloc(sizeof(char)*10000);
memset(vs, 0, sizeof(char)*10000);
memset(fs, 0, sizeof(char)*10000);

FILE *fp;
char c;
int count;

fp=fopen("checkerboard.vs", "r");
count=0;
while((c=fgetc(fp)) != EOF)
{
vs[count]=c;
count++;
}
fclose(fp);

fp=fopen("checkerboard.fs", "r");
count=0;
while((c=fgetc(fp)) != EOF)
{
fs[count]=c;
count++;
}
fclose(fp);

printf("Hello\n");

v=glCreateShader(GL_VERTEX_SHADER);
f=glCreateShader(GL_FRAGMENT_SHADER);

const char *vv;
const char *ff;
vv=vs;
ff=fs;

glShaderSource(v, 1, &vv, NULL);
glShaderSource(f, 1, &ff, NULL);

int success;

glCompileShader(v);
glGetShaderiv(v, GL_COMPILE_STATUS, &success);
if(!success)
{
char info_log[5000];
glGetShaderInfoLog(v, 5000, NULL, info_log);
printf("Error in vertex shader compilation!\n");
printf("Info Log: %s\n", info_log);
}

glCompileShader(f);
glGetShaderiv(f, GL_COMPILE_STATUS, &success);
if(!success)
{
char info_log[5000];
glGetShaderInfoLog(f, 5000, NULL, info_log);
printf("Error in fragment shader compilation!\n");
printf("Info Log: %s\n", info_log);
}

p=glCreateProgram();
glAttachShader(p, v);
glAttachShader(p, f);
glLinkProgram(p);
glUseProgram(p);

free(vs);
free(fs);
}

void init()
{
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);

glewInit();
set_shaders();
}

void display_func()
{
glEnable(GL_DEPTH_TEST);

glClearColor(0.75f, 0.75f, 0.75f, 0.25f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glPushMatrix();

if(buttonState == 1)
{
xRot+=(xRotLength-xRot)*0.1f;
yRot+=(yRotLength-yRot)*0.1f;
}

glTranslatef(xTrans, yTrans, zTrans);
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);

glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
glEnable(GL_LIGHT1);

draw_box(-10.0f, -10.0f, -10.0f, 20.0f, 20.0f, 20.0f);
glColor3f(1.0f, 0.0f, 0.0f);

GLint uniformLoc = glGetUniformLocation(p, "lightPos");
    if (uniformLoc != -1)
    {
        glUniform3fv(uniformLoc, 1, LightPosition);
    }

glutSolidSphere(8.0, 300, 300);

glPopMatrix();

    glutSwapBuffers();
}

void idle_func()
{
glutPostRedisplay();
}

void reshape_func(GLint width, GLint height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(45.0, (float)width/height, 0.001, 100.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -3.0f);
}

void keyboard_func(unsigned char key, int x, int y)
{
if(key == 'w')
{
zTrans += 2.0f;
}

if(key == 's')
{
zTrans -= 2.0f;
}

if(key == 'a')
{
xTrans -= 2.0f;
}

if(key == 'd')
{
xTrans += 2.0f;
}

if(key == 'q')
{
yTrans -= 2.0f;
}

if(key == 'e')
{
yTrans += 2.0f;
}

glutPostRedisplay();
}

void specialkey_func(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
{
zTrans += 2.0f;
}

if(key == GLUT_KEY_DOWN)
{
zTrans -= 2.0f;
}

if(key == GLUT_KEY_LEFT)
{
xTrans -= 2.0f;
}

if(key == GLUT_KEY_RIGHT)
{
xTrans += 2.0f;
}

glutPostRedisplay();
}

void mouse_func(int button, int state, int x, int y)
{
if (state == GLUT_DOWN)
{
        buttonState = 1;
}
    else if (state == GLUT_UP)
{
        buttonState = 0;
}

    ox = x; oy = y;

    glutPostRedisplay();
}

void motion_func(int x, int y)
{
    float dx, dy;
    dx = (float)(x - ox);
    dy = (float)(y - oy);

if (buttonState == 1) 
{
xRotLength += dy / 5.0f;
yRotLength += dx / 5.0f;
}

ox = x; oy = y;

glutPostRedisplay();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH  | GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(window_width, window_height);
    glutCreateWindow("Sphere");

init();

    glutDisplayFunc(display_func);
glutReshapeFunc(reshape_func);
glutSpecialFunc(specialkey_func);
glutKeyboardFunc(keyboard_func);
glutMouseFunc(mouse_func);
glutMotionFunc(motion_func);
glutIdleFunc(idle_func);

glEnable(GL_DEPTH_TEST);

    glutMainLoop();

    return 0;
}

Vertex Shader程序
// checkerboard.vs
//
// Generic vertex transformation,
// copy object-space position and 
// lighting vectors out to interpolants

uniform vec3 lightPos;

varying vec3 N, L, V;

void main(void)
    // normal MVP transform
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    // map object-space position onto unit sphere
    V = gl_Vertex.xyz;

    // eye-space normal
    N = gl_NormalMatrix * gl_Normal;

    // eye-space light vector
    vec4 Veye = gl_ModelViewMatrix * gl_Vertex;
    L = lightPos - Veye.xyz;
}

Fragment Shader程序
// checkerboard.fs
//
// 3D solid checker grid

varying vec3 V; // object-space position
varying vec3 N; // eye-space normal
varying vec3 L; // eye-space light vector

const vec3 onColor = vec3(1.0, 1.0, 1.0);
const vec3 offColor = vec3(0.0, 0.0, 0.0);

const float ambientLighting = 0.2;
const float specularExp = 60.0;
const float specularIntensity = 0.75;

const int numSquaresPerSide = 8;


void main (void)
{
    // Normalize vectors
    vec3 NN = normalize(N);
    vec3 NL = normalize(L);
    vec3 NV = normalize(V);
    vec3 NH = normalize(NL + vec3(0.0, 0.0, 1.0));

    // Map -1,1 to 0,numSquaresPerSide
    vec3 onOrOff = ((NV + 1.0) * float(numSquaresPerSide)) / 2.0;
    // mod 2 >= 1
    onOrOff = step(1.0, mod(onOrOff, 2.0));
    // 3-way xor
    onOrOff.x = step(0.5, 
        mod(onOrOff.x + onOrOff.y + onOrOff.z, 2.0));

    // checkerboard grid
    vec3 surfColor = mix(offColor, onColor, onOrOff.x);

    // calculate diffuse lighting + 20% ambient
    surfColor *= (ambientLighting + vec3(max(0.0, dot(NN, NL))));

    // calculate specular lighting w/ 75% intensity
    surfColor += (specularIntensity * 
        vec3(pow(max(0.0, dot(NN, NH)), specularExp)));

    gl_FragColor = vec4(surfColor, 1.0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值