我想学习OpenGL,并决定从一个非常简单的例子开始 - 渲染彗星Wild 2的形状,这是从Stardust太空船的测量结果推断出来的(有关http://nssdc.gsfc.nasa.gov/nmc/masterCatalog.do?ds=PSSB-00133中数据的详细信息)。请记住,我完全不了解OpenGL。一些Google-fu帮助我获得了下面提供的代码。尽管我付出了最大的努力,我的彗星很糟糕:
我希望它看起来更漂亮,我不知道如何继续(除了阅读红皮书,或类似)。例如:
如何让这个怪物看起来更漂亮?是否有对在线教程或代码示例的引用?
我在bitbucket中放置了源代码,数据和makefile(用于OS X):
hg clone https://arrieta@bitbucket.org/arrieta/learning-opengl
数据包括8,761个三元组(顶点,在一个固定的框架中)和17,518个三角形(每个三角形是一个整数的三元组,指的是8,761个顶点三元组之一)。
#include<stdio.h>
#include<stdlib.h>
#include<OpenGL/gl.h>
#include<OpenGL/glu.h>
// I added this in case you want to "copy/paste" the program into a
// non-Mac computer
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
/* I hardcoded the data and use globals. I know it sucks, but I was in
a hurry. */
#define NF 17518
#define NV 8761
unsigned int fs[3 * NF];
float vs[3 * NV];
float angle = 0.0f;
/* callback when the window changes size (copied from Internet example) */
void changeSize(int w, int h) {
if (h == 0) h = 1;
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45.0f, ratio, 0.2f, 50000.0f); /* 45 degrees fov in Y direction; 50km z-clipping*/
glMatrixMode(GL_MODELVIEW);
}
/* this renders and updates the scene (mostly copied from Internet examples) */
void renderScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 10000.0f, /* eye is looking down along the Z-direction at 10km */
0.0f, 0.0f, 0.0f, /* center at (0, 0, 0) */
0.0f, 1.0f, 0.0f); /* y direction along natural y-axis */
/* just add a simple rotation */
glRotatef(angle, 0.0f, 0.0f, 1.0f);
/* use the facets and vertices to insert triangles in the buffer */
glBegin(GL_TRIANGLES);
unsigned int counter;
for(counter=0; counter<3 * NF; ++counter) {
glVertex3fv(vs + 3 * fs[counter]); /* here is where I'm loading
the data - why do I need to
load it every time? */
}
glEnd();
angle += 0.1f; /* update the rotation angle */
glutSwapBuffers();
}
int main(int argc, char* argv[]) {
FILE *fp;
unsigned int counter;
/* load vertices */
fp = fopen("wild2.vs", "r");
counter = 0;
while(fscanf(fp, "%f", &vs[counter++]) > 0);
fclose(fp);
/* load facets */
fp = fopen("wild2.fs", "r");
counter = 0;
while(fscanf(fp, "%d", &fs[counter++]) > 0);
fclose(fp);
/* this initialization and "configuration" is mostly copied from Internet */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(1024, 1024);
glutCreateWindow("Wild-2 Shape");
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 30.0 };
GLfloat light_position[] = {3000.0, 3000.0, 3000.0, 0.0 };
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glutMainLoop();
return 0;
}
它开始看起来更好了,我现在有足够的资源来暂时考虑。它仍然很糟糕,但我的问题已得到解答!
我添加了法线,可以在“纹理”和线框之间来回切换:
PS。 repository显示根据SeedmanJ的建议所做的更改。
答案 0 :(得分:3)
在OpenGL中更改为线框渲染非常容易,您必须使用
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
并切换回填充渲染,
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
关于灯光,OpenGL允许您使用最多8种不同的灯光,通过法线和材料生成最终渲染。您可以使用以下命令激活照明模式:
glEnable(GL_LIGHTING);
然后使用以下任一项激活每个灯光:
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
改变像它的位置一样的光属性,请看一下 http://linux.die.net/man/3/gllightfv
如果你使用glBegin()方法,你必须为你定义的每个顶点设置法线。在VBO渲染中它是相同的但是法线也包含在vram中。在glBegin()方法中,您可以使用
glNormal3f(x, y, z); for example
为您定义的每个顶点。
有关您可以做什么的更多信息,红皮书是一个很好的开始方式。
移动你的场景&#34;是OpenGL间接允许你做的另一件事。因为这一切都适用于矩阵,
你可以使用
glTranslate3f(x, y, z);
glRotate3f(num, x, y, z);
....
管理关键事件和鼠标事件(我几乎可以肯定)与OpenGL无关,它取决于你使用的lib,例如glut / SDL / ...所以你会这样做必须参考他们自己的文件。
最后,有关您可以使用的某些功能的更多信息,http://www.opengl.org/sdk/docs/man/,还有一个教程部分,引导您访问不同的有趣网站。
希望这有帮助!
答案 1 :(得分:1)
如何对形状进行非常基本的“线框”渲染?
glPolygonMode( GL_FRONT, GL_LINE );
假设太阳位于“底部”方向(即沿-Y),我如何添加光线并看到另一侧的阴影?
好的阴影很难,尤其是固定功能管道。
但在此之前,你需要normals来配合你的顶点。您可以计算per-face normals pretty easily。
如何添加“鼠标事件”以便我可以旋转视图,放大/缩小?
尝试使用鼠标处理程序here。
答案 2 :(得分:-7)
虽然我有点想说“从更简单的事情开始”,但我认为,有时你需要“潜入”以便在很短的时间内获得良好的理解!做得好!
如果您想要一个例子,请问...... 我写的文档很好,效率很高, 但可读的纯Win32(无.NET或MFC)OpenGL FPS!
虽然看来其他人回答你们大部分的问题...... 如果你愿意,我可以帮助你,也许你可以制作一个很酷的质地(如果你没有)......
回答这个问题:
glBegin(GL_TRIANGLES);
unsigned int counter;
for(counter=0; counter<3 * NF; ++counter) {
glVertex3fv(vs + 3 * fs[counter]); /* here is where I'm loading
the data - why do I need to
load it every time? */
}
glEnd();
即呈现3D模型的顶点(在视图已更改的情况下) 并使用DC(设备上下文),将BitBlt用于窗口! 它必须重复进行(如果某些事情导致窗口清除)......