gpt4 book ai didi

c++ - 轨道球体应将聚光灯转换到中央立方体上

转载 作者:太空狗 更新时间:2023-10-29 21:26:02 26 4
gpt4 key购买 nike

我正在编写一个程序,它在屏幕中间绘制一个旋转的立方体(带有纹理),然后是一个围绕立方体旋转的黄色小球体。这个想法是让球体成为照亮立方体的点光源。

这是问题所在:正如您在下图中所见,我未能实现聚光灯效果。似乎整个立方体都被点亮了:

我将 GL_SPOT_DIRECTION 设置为立方体位置。我没有设置表面法线,因为我正在努力理解如何为立方体计算它们,而且我不确定像这样的简单图形应用程序是否真的需要它。

我正在分享下面的代码:

ma​​in.cpp:

#include <QApplication>
#include "glwidget.h"

int main(int argc, char* argv[])
{
QApplication app(argc, argv);

GLWidget gl_widget;
gl_widget.show();

return app.exec();
}

GLWidget.h:

#pragma once
#include <QGLWidget>
#include <QImage>

class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget* parent = 0);
virtual ~GLWidget();

void _draw_texture_cube(int w, int h);
void _draw_light();

/* OpenGL initialization, viewport resizing, and painting */

void initializeGL();
void paintGL();
void resizeGL( int width, int height);

/* enable the user to interact directly with the scene using the keyboard */

void keyPressEvent(QKeyEvent *e);

private:
int _width;
int _height;
QImage* _img;
GLuint _texture;
float xrot;
float yrot;
float zrot;
bool _light_on;
bool _must_rotate;
bool _pause_light;
GLfloat _light_pos[3];
GLfloat _cube_pos[3];
GLUquadricObj* _quadratic;

protected slots:
void _tick();
};

GLWidget.cpp:

#include "GLWidget.h"

#include <iostream>
#include <QKeyEvent>
#include <QTimer>

#include <cmath>

#define LIGHT_MOVEMENT_SPEED 20.0f // Degrees per second
#define pi 3.141592654f

GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent), _img(NULL), _light_on(true), _must_rotate(true),
_pause_light(false), _quadratic(NULL)
{
_width = 0;
_height = 0;
_texture = 0;

xrot = 0.f;
yrot = 0.f;
zrot = 0.f;

// Set central cube position
_cube_pos[0] = 0.0f;
_cube_pos[1] = 0.0f;
_cube_pos[2] = -7.0f;

// Set light position
_light_pos[0] = 0.5f;
_light_pos[1] = 0.5f;
_light_pos[2] = -7.0f;
}

GLWidget::~GLWidget()
{
if (_img)
delete _img;

glDeleteTextures(1, &_texture);
}

void GLWidget::_tick()
{
update(); // triggers paintGL()

QTimer::singleShot(33, this, SLOT(_tick()));
}

void GLWidget::initializeGL()
{
std::cout << "GLWidget::initializeGL" << std::endl;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Background

glEnable(GL_CULL_FACE);

/* Load bitmap */

glEnable(GL_TEXTURE_RECTANGLE_ARB);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);

if (!_img)
{
std::cout << "GLWidget::paintGL: loading image" << std::endl;

QImage tmp(":/crate.jpg");
if (tmp.isNull())
{
std::cout << "GLWidget::paintGL: !!! Failed QImage #1" << std::endl;
return;
}

_img = new QImage(QGLWidget::convertToGLFormat(tmp));
}

/* Convert bitmap into texture */

// Create The Texture
glGenTextures(1, &_texture);

// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture);

// Generate The Texture
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
GL_RGBA, _img->width(), _img->height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, _img->bits());

if (glGetError() != GL_NO_ERROR)
{
std::cout << "GLWidget::paintGL: !!! Failed glTexImage2D" << std::endl;
return;
}

/* Setup lighting */

glShadeModel(GL_SMOOTH); //Smooth color shading

// Light properties
GLfloat AmbientLight[4] = {0.2, 0.2, 0.2, 1.0};
GLfloat DiffuseLight[4] = {0.8, 0.8, 0.8, 1.0}; // color
GLfloat SpecularLight[4] = {1.0, 1.0, 1.0, 1.0}; // bright
GLfloat SpecRef[] = {0.7f, 0.7f, 0.7f, 1.0f};
GLubyte Shine = 60.0;

//glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, AmbientLight);
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight);
glLightfv(GL_LIGHT0, GL_POSITION, _light_pos);

glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_SPECULAR, SpecRef); // refletância do material
glMaterialf(GL_FRONT, GL_SHININESS, Shine); // concentração do brilho
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
//glColorMaterial(GL_FRONT,GL_DIFFUSE);

glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);

// Sphere
_quadratic = gluNewQuadric(); // Create A Pointer To The Quadric Object
gluQuadricNormals(_quadratic, GLU_SMOOTH); // Create Smooth Normals
gluQuadricTexture(_quadratic, GL_TRUE); // Create Texture Coords

/* Start the timer */

_tick();
}

/* Draw the central cube with texture
*/
void GLWidget::_draw_texture_cube(int w, int h)
{
glPushMatrix();

glTranslatef(_cube_pos[0], _cube_pos[1], _cube_pos[2]);
glRotatef ( xrot, 1.0, 0.0, 0.0 );
glRotatef ( yrot, 0.0, 1.0, 0.0 );
glRotatef ( zrot, 0.0, 0.0, 1.0 );

glColor3f(1.0f, 1.0f, 1.0f);

glBegin(GL_QUADS); // Draw A Cube

// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(w, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(w, h); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, h); glVertex3f(-1.0f, 1.0f, 1.0f);

// Back Face
glTexCoord2f(w, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(w, h); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, h); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);

// Top Face
glTexCoord2f(0.0f, h); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(w, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(w, h); glVertex3f( 1.0f, 1.0f, -1.0f);

// Bottom Face
glTexCoord2f(w, h); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, h); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(w, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);

// Right face
glTexCoord2f(w, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(w, h); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, _img->height()); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);

// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(w, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(w, h); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, h); glVertex3f(-1.0f, 1.0f, -1.0f);

glEnd();
glPopMatrix();

if (_must_rotate)
{
xrot += 0.6f;
yrot += 0.4f;
zrot += 0.8f;
}
}

/* Draw light source and light model (sphere)
*/
void GLWidget::_draw_light()
{
if (_light_on)
{
glEnable(GL_LIGHT0); // enable lights that we use
}
else
{
glDisable(GL_LIGHT0);
}

static float light_angle = 25.0f;
if (!_pause_light) // stop moving the light source
{
light_angle += LIGHT_MOVEMENT_SPEED * 0.1;
if (light_angle > 360.0f)
light_angle -= 360.0f;
}

/* Set light source position */

_light_pos[0] = 4.0f * (float) cos(light_angle * pi / 180.0f);
_light_pos[1] = 4.0f * (float) sin(light_angle * pi / 180.0f);
_light_pos[2] = -7;
glLightfv(GL_LIGHT0, GL_POSITION, _light_pos);

GLfloat SpotDir[] = {_cube_pos[0], _cube_pos[1], _cube_pos[2], 0.0 };
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, SpotDir);

glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 150.0);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 15.0);

/* Set the light model position to be the same as the light source */

glPushMatrix();
glTranslatef(_light_pos[0], _light_pos[1], _light_pos[2]);
glColor3ub(255, 255, 0); // yellow
gluSphere(_quadratic, 0.2f, 32, 32); // draw sphere
glPopMatrix();
}

void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix
glLoadIdentity(); // Reset The Current Modelview Matrix

/* Draw central cube */

glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture); // Select Our Texture
_draw_texture_cube(_img->width(), _img->height());
glDisable(GL_TEXTURE_RECTANGLE_ARB);

/* Draw light source and light model*/

_draw_light();
}

void GLWidget::resizeGL( int w, int h)
{
_width = w;
_height = h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
if (h == 0) // Calculate The Aspect Ratio Of The Window
gluPerspective ( 60, ( float ) w, 0.4, 500.0 );
else
gluPerspective ( 60, ( float ) w / ( float ) h, 0.4, 500.0 );

glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix
glLoadIdentity ( ); // Reset The Model View Matrix
gluLookAt(0.0, 0.0, 2.0, // eye
0.0, 0.0, 0.0, // center
0.0, 1.0, 0.0); // up
}

void GLWidget::keyPressEvent(QKeyEvent *e)
{
switch (e->key())
{
case Qt::Key_L:
if (_light_on)
_light_on = false;
else
_light_on = true;
break;

case Qt::Key_P:
if (_pause_light)
_pause_light = false;
else
_pause_light = true;
break;

case Qt::Key_R:
if (_must_rotate)
_must_rotate = false;
else
_must_rotate = true;
break;

default:
break;
}
}

Lighting.pro:

QT += core gui opengl

SOURCES += \
GLWidget.cpp \
main.cpp

HEADERS += \
GLWidget.h

RESOURCES += \
resource.qrc

为了达到预期的效果,这个应用需要改变什么?

最佳答案

您没有为立方体面指定任何法线。由于 OpenGL 是一个状态机,它将对所有顶点使用默认的表面法线,因此您的所有面。由于法 vector 对照明至关重要,所以你所有的脸都会被照亮几乎相同(顶点位置仍然不同,但效果很弱)。

您还应该知道,OpenGL 的固定功能照明是按顶点完成的。如果你真的想在曲线上看到一个好的聚光灯,你要么需要对其进行 segmentation ,以便在实际计算光照方程的地方使用更多的顶点,要么使用着色器进行逐片段光照。

关于c++ - 轨道球体应将聚光灯转换到中央立方体上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12790936/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com