精华内容
下载资源
问答
  • opengl 球体

    2019-11-17 00:09:21
    理论:球的参数方程 ... 不过我这里是y 与z的参数方程交换了关系式。即y=Rcos(φ),注意我这里代码没有实现计算法向量数组,如果后期我用到了再加。(个人笔记,不喜勿喷) 效果: ...//H x-z平面圆分成多少...

    理论:球的参数方程

    https://baike.baidu.com/item/%E7%90%83%E9%9D%A2/5889102?fr=aladdin

    不过我这里是y 与z的参数方程交换了关系式。即y=Rcos(φ),注意我这里代码没有实现计算法向量数组,如果后期我用到了再加。(个人笔记,不喜勿喷)

    效果:

     画球代码:

    int H=40, V=40;//H x-z平面圆分成多少份,V是y轴分成多少份 
    const float PI = 3.141592653;
    float HR =2*PI / H;
    float VR = PI / V;
    
    float R = 0.5;   //圆半径
    int vSize = (V - 1)*H + 2;    //顶点数量
    int indexSize = (2 * (V - 2)*H + 2 * H) * 3;//索引 ,glDrawElements使用
    
    struct VertexM
    {
    	float X;
    	float Y;
    	float Z;
    };
    
    
    vector<VertexM> vertexs;//顶点数组
    vector<unsigned int> indexs; //索引 ,glDrawElements使用
    
    void drawSphere() {
    	vertexs.clear();
    	indexs.clear();
    
    	for (size_t i = 0; i <= V; i++)
    	{
    		if (i==0)
    		{
    			VertexM vertex;
    			vertex.X = 0;
    			vertex.Y = R;
    			vertex.Z = 0;
    			vertexs.push_back(vertex);
    			continue;
    		}
    		else if (i==V)
    		{
    			VertexM vertex;
    			vertex.X = 0;
    			vertex.Y = -R;
    			vertex.Z = 0;
    			vertexs.push_back(vertex);
    
    			for (int t = H-1; t>=0 ; t--)
    			{
    				//球次最后各顶点与最后一个顶点的三角形索引
    				indexs.push_back(vSize - 1);
    				unsigned int temIndex = ((i - 2) * H + 1 + t);
    				indexs.push_back(temIndex);
    
    				if (t == 0)
    				{
    					indexs.push_back(temIndex + H - 1);
    				}
    				else
    				{
    					indexs.push_back(temIndex - 1);
    				}
    			
    			}
    
    			continue;
    		}
    	
    		float theta = VR*i;
    		for (size_t j = 0; j < H; j++)
    		{
    			float temX, temY, temZ,beta;
    			beta = HR*j;
    		
    			temX = R*sin(theta)*sin(beta);
    			temY = R*cos(theta);
    			temZ = R*sin(theta)*cos(beta);
    
    
    			VertexM vertex;
    			vertex.X = temX;
    			vertex.Y = temY;
    			vertex.Z = temZ;
    
    			vertexs.push_back(vertex);
    
    
    			//index
    			if (i==1)
    			{
    				indexs.push_back(0);
    				indexs.push_back(j + 1);
    				if (j==H-1)
    				{
    				 indexs.push_back(1);
    				}
    				else
    				{
    					indexs.push_back(j + 2);
    				}
    			}
    			else
    			{
    				//三角形1
    				unsigned int tem1 = H*(i - 2) + 1 + j;
    				unsigned int tem2 = H*(i - 1) + 1 + j;
    				unsigned int tem3 = H*(i - 2) + 2 + j;
    				unsigned int tem4 = H*(i - 2) + 1;
    
    				indexs.push_back(tem1);
    				indexs.push_back(tem2);
    				if (j == H - 1)
    				{
    					indexs.push_back(tem4);
    				}
    				else
    				{
    					indexs.push_back(tem3);
    				}
    				//三角形2
    				unsigned int tem5 = tem2;
    				unsigned int tem6 = H*(i - 1) + 2 + j;
    				unsigned int tem7 = tem3;
    				unsigned int tem8 = H*(i - 1) + 1;
    				unsigned int tem9 = H*(i - 2) + 1;
    
    				indexs.push_back(tem5);
    
    				if (j == H - 1)
    				{
    					indexs.push_back(tem8);
    					indexs.push_back(tem9);
    				}
    				else
    				{
    					indexs.push_back(tem6);
    					indexs.push_back(tem7);
    				}
    
    			}
    		
    		}
    	}
    	unsigned int ad1 = vertexs.size();
    	unsigned int ad2= indexs.size();
    }

     VA0,VB0,EBO:

    unsigned VAO, VBO, EBO;
    	glGenVertexArrays(1,&VAO);
    	glBindVertexArray(VAO);
    	glGenBuffers(1,&VBO);
    	glBindBuffer(GL_ARRAY_BUFFER,VBO);
    	glBufferData(GL_ARRAY_BUFFER,vertexs.size()* sizeof(VertexM),&vertexs[0],GL_STATIC_DRAW);
    	glGenBuffers(1,&EBO);
    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
    	glBufferData(GL_ELEMENT_ARRAY_BUFFER,indexs.size()* sizeof(unsigned int),&indexs[0],GL_STATIC_DRAW);
    	glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    	glEnableVertexAttribArray(0);
    	glBindBuffer(GL_ARRAY_BUFFER,0);
    	glBindVertexArray(0);

    draw:

            glBindVertexArray(VAO);
    		glDrawElements(GL_TRIANGLE_STRIP, indexSize, GL_UNSIGNED_INT, 0);
    		glBindVertexArray(0);

     

     

     

     

     

    展开全文
  • OpenGL球体绘制与球体贴图
  • OpenGL球体的Phong渲染

    2021-03-21 14:15:05
    OpenGL球体的Phong渲染先上图,再解答。完整主要的源代码源代码剖析 先上图,再解答。 完整主要的源代码 #include <stdio.h> #include "GL/glus.h" struct LightProperties { GLfloat direction[3]; ...

    先上图,再解答。

    在这里插入图片描述

    完整主要的源代码

    #include <stdio.h>
    #include "GL/glus.h"
    struct LightProperties
    {
        GLfloat direction[3];
        GLfloat ambientColor[4];
        GLfloat diffuseColor[4];
        GLfloat specularColor[4];
    };
    struct MaterialProperties
    {
        GLfloat ambientColor[4];
        GLfloat diffuseColor[4];
        GLfloat specularColor[4];
        GLfloat specularExponent;
    };
    
    struct LightLocations
    {
        GLint directionLocation;
        GLint ambientColorLocation;
        GLint diffuseColorLocation;
        GLint specularColorLocation;
    };
    
    
    struct MaterialLocations
    {
        GLint ambientColorLocation;
        GLint diffuseColorLocation;
        GLint specularColorLocation;
        GLint specularExponentLocation;
    };
    
    static GLUSprogram g_program;
    
    
    static GLint g_projectionMatrixLocation;
    
    
    static GLint g_modelViewMatrixLocation;
    
    static GLint g_normalMatrixLocation;
    
    
    static struct LightLocations g_light;
    
    static struct MaterialLocations g_material;
    
    static GLint g_vertexLocation;
    
    static GLint g_normalLocation;
    
    static GLuint g_verticesVBO;
    
    static GLuint g_normalsVBO;
    
    static GLuint g_indicesVBO;
    
    static GLuint g_vao;
    
    static GLuint g_numberIndicesSphere;
    
    GLUSboolean init(GLUSvoid)
    {
        GLfloat viewMatrix[16];
        GLfloat normalMatrix[9];
    
        struct LightProperties light = { { 1.0f, 1.0f, 1.0f }, { 0.3f, 0.3f, 0.3f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } };
    
        struct MaterialProperties material = { { 0.0f, 0.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, 20.0f };
    
        GLUStextfile vertexSource;
        GLUStextfile fragmentSource;
    
        GLUSshape sphere;
    
        glusFileLoadText("../Example05/shader/phong.vert.glsl", &vertexSource);
        glusFileLoadText("../Example05/shader/phong.frag.glsl", &fragmentSource);
    
        glusProgramBuildFromSource(&g_program, (const GLUSchar**) &vertexSource.text, 0, 0, 0, (const GLUSchar**) &fragmentSource.text);
    
        glusFileDestroyText(&vertexSource);
        glusFileDestroyText(&fragmentSource);
    
    
        g_projectionMatrixLocation = glGetUniformLocation(g_program.program, "u_projectionMatrix");
        g_modelViewMatrixLocation = glGetUniformLocation(g_program.program, "u_modelViewMatrix");
        g_normalMatrixLocation = glGetUniformLocation(g_program.program, "u_normalMatrix");
    
        g_light.directionLocation = glGetUniformLocation(g_program.program, "u_light.direction");
        g_light.ambientColorLocation = glGetUniformLocation(g_program.program, "u_light.ambientColor");
        g_light.diffuseColorLocation = glGetUniformLocation(g_program.program, "u_light.diffuseColor");
        g_light.specularColorLocation = glGetUniformLocation(g_program.program, "u_light.specularColor");
    
        g_material.ambientColorLocation = glGetUniformLocation(g_program.program, "u_material.ambientColor");
        g_material.diffuseColorLocation = glGetUniformLocation(g_program.program, "u_material.diffuseColor");
        g_material.specularColorLocation = glGetUniformLocation(g_program.program, "u_material.specularColor");
        g_material.specularExponentLocation = glGetUniformLocation(g_program.program, "u_material.specularExponent");
    
        g_vertexLocation = glGetAttribLocation(g_program.program, "a_vertex");
        g_normalLocation = glGetAttribLocation(g_program.program, "a_normal");
    
        glusShapeCreateSpheref(&sphere, 0.5f, 32);
    
        g_numberIndicesSphere = sphere.numberIndices;
    
        glGenBuffers(1, &g_verticesVBO);
        glBindBuffer(GL_ARRAY_BUFFER, g_verticesVBO);
        glBufferData(GL_ARRAY_BUFFER, sphere.numberVertices * 4 * sizeof(GLfloat), (GLfloat*) sphere.vertices, GL_STATIC_DRAW);
    
        glGenBuffers(1, &g_normalsVBO);
        glBindBuffer(GL_ARRAY_BUFFER, g_normalsVBO);
        glBufferData(GL_ARRAY_BUFFER, sphere.numberVertices * 3 * sizeof(GLfloat), (GLfloat*) sphere.normals, GL_STATIC_DRAW);
    
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    
        glGenBuffers(1, &g_indicesVBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesVBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphere.numberIndices * sizeof(GLuint), (GLuint*) sphere.indices, GL_STATIC_DRAW);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
        glusShapeDestroyf(&sphere);
    
    
    
        glUseProgram(g_program.program);
    
        glGenVertexArrays(1, &g_vao);
        glBindVertexArray(g_vao);
    
        glBindBuffer(GL_ARRAY_BUFFER, g_verticesVBO);
        glVertexAttribPointer(g_vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(g_vertexLocation);
    
        glBindBuffer(GL_ARRAY_BUFFER, g_normalsVBO);
        glVertexAttribPointer(g_normalLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(g_normalLocation);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesVBO);
    
    
        glusMatrix4x4LookAtf(viewMatrix, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    
    
        glusMatrix4x4ExtractMatrix3x3f(normalMatrix, viewMatrix);
    
        glUniformMatrix4fv(g_modelViewMatrixLocation, 1, GL_FALSE, viewMatrix);
        glUniformMatrix3fv(g_normalMatrixLocation, 1, GL_FALSE, normalMatrix);
    
    
    
        glusVector3Normalizef(light.direction);
    
    
        glusMatrix4x4MultiplyVector3f(light.direction, viewMatrix, light.direction);
    
    
        glUniform3fv(g_light.directionLocation, 1, light.direction);
        glUniform4fv(g_light.ambientColorLocation, 1, light.ambientColor);
        glUniform4fv(g_light.diffuseColorLocation, 1, light.diffuseColor);
        glUniform4fv(g_light.specularColorLocation, 1, light.specularColor);
    
    
        glUniform4fv(g_material.ambientColorLocation, 1, material.ambientColor);
        glUniform4fv(g_material.diffuseColorLocation, 1, material.diffuseColor);
        glUniform4fv(g_material.specularColorLocation, 1, material.specularColor);
        glUniform1f(g_material.specularExponentLocation, material.specularExponent);
    
    
    
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
        glClearDepth(1.0f);
    
        glEnable(GL_DEPTH_TEST);
    
        glEnable(GL_CULL_FACE);
    
        return GLUS_TRUE;
    }
    
    GLUSvoid reshape(GLUSint width, GLUSint height)
    {
        GLfloat projectionMatrix[16];
    
        glViewport(0, 0, width, height);
    
        glusMatrix4x4Perspectivef(projectionMatrix, 40.0f, (GLfloat) width / (GLfloat) height, 1.0f, 100.0f);
    
        glUniformMatrix4fv(g_projectionMatrixLocation, 1, GL_FALSE, projectionMatrix);
    }
    
    GLUSboolean update(GLUSfloat time)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glDrawElements(GL_TRIANGLES, g_numberIndicesSphere, GL_UNSIGNED_INT, 0);
    
        return GLUS_TRUE;
    }
    
    GLUSvoid terminate(GLUSvoid)
    {
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    
        if (g_verticesVBO)
        {
            glDeleteBuffers(1, &g_verticesVBO);
    
            g_verticesVBO = 0;
        }
    
        if (g_normalsVBO)
        {
            glDeleteBuffers(1, &g_normalsVBO);
    
            g_normalsVBO = 0;
        }
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
        if (g_indicesVBO)
        {
            glDeleteBuffers(1, &g_indicesVBO);
    
            g_indicesVBO = 0;
        }
    
        glBindVertexArray(0);
    
        if (g_vao)
        {
            glDeleteVertexArrays(1, &g_vao);
    
            g_vao = 0;
        }
    
        glUseProgram(0);
    
        glusProgramDestroy(&g_program);
    }
    
    int main(int argc, char* argv[])
    {
    	EGLint eglConfigAttributes[] = {
    	        EGL_RED_SIZE, 8,
    	        EGL_GREEN_SIZE, 8,
    	        EGL_BLUE_SIZE, 8,
    	        EGL_DEPTH_SIZE, 24,
    	        EGL_STENCIL_SIZE, 0,
    	        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
    	        EGL_NONE
    	};
    
        EGLint eglContextAttributes[] = {
        		EGL_CONTEXT_MAJOR_VERSION, 3,
        		EGL_CONTEXT_MINOR_VERSION, 2,
        		EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, EGL_TRUE,
        		EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
        		EGL_NONE
        };
    
        glusWindowSetInitFunc(init);
    
        glusWindowSetReshapeFunc(reshape);
    
        glusWindowSetUpdateFunc(update);
    
        glusWindowSetTerminateFunc(terminate);
    
        if (!glusWindowCreate("it_xiangqiang  Example Window", 640, 480, GLUS_FALSE, GLUS_FALSE, eglConfigAttributes, eglContextAttributes, 0))
        {
            printf("Could not create window!\n");
            return -1;
        }
    
        glusWindowRun();
    
        return 0;
    }
    
    

    源代码剖析

    struct LightProperties light = { { 1.0f, 1.0f, 1.0f }, { 0.3f, 0.3f, 0.3f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } };//这是白光。
    struct MaterialProperties material = { { 0.0f, 0.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, 20.0f };//具有白色镜面反射颜色的蓝色材料。
    glusShapeCreateSpheref(&sphere, 0.5f, 32);//具有白色镜面反射颜色的蓝色材料。
    glusMatrix4x4ExtractMatrix3x3f(normalMatrix, viewMatrix); //计算是在相机/视图空间中完成的。 因此,传递视图矩阵,这是一个刚体变换。
    glusMatrix4x4MultiplyVector3f(light.direction, viewMatrix, light.direction);//将光转换为摄影机空间,就像目前在世界空间中一样
    glUniform3fv(g_light.directionLocation, 1, light.direction);//设置灯glUniform4fv(g_material.ambientColorLocation, 1, material.ambientColor);//材质的值
    glUniformMatrix4fv(g_projectionMatrixLocation, 1, GL_FALSE, projectionMatrix);//只需传递投影矩阵即可。 最终矩阵在着色器中计算。

    展开全文
  • OpenGL 球体世界

    2019-10-02 22:30:03
    一、类似公自转 二、核心代码 //图形渲染 void RenderScene() ... //清楚缓存区:颜色缓存区、深度缓存区、模版缓存区 ... glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER... //设置颜色:地板、甜甜圈、球体 GLflo...

    一、类似公自转

    二、核心代码

    //图形渲染

    void RenderScene()
    {
        //清楚缓存区:颜色缓存区、深度缓存区、模版缓存区
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
        
        //设置颜色:地板、甜甜圈、球体
        GLfloat vFloorColor[] = {0.0f, 1.0f, 0.0f, 1.0f};
        GLfloat vTorusColor[] = {1.0f, 0.0f, 0.0f, 1.0f};
        GLfloat vSphereColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
        
        //基于当前时间动画:当前时间*60s
        static CStopWatch rotTime;
        float yRot = rotTime.GetElapsedSeconds()*60.0f;
        
        //获取观察者矩阵并入栈
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        modelViewMatrix.PushMatrix(mCamera);
        
        //设置光源矩阵
        M3DVector4f vLightPos = {0.0f, 10.0f, 5.0f, 1.0f};
        M3DVector4f vLightEyePos;
        //将光源矩阵和观察者矩阵相乘的结果放在vLightEyePos中
        m3dTransformVector4(vLightEyePos, vLightPos, mCamera);
        
        //使用管线控制器,平面着色器进行渲染
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor);
        floorBatch.Draw();
        
        //在模型视图矩阵堆栈中绘制以下图形:先压栈,绘制完毕后再出栈——始终对栈顶矩阵图形渲染
        
        //绘制随机球体
        for (int i = 0; i < NUM_SPHERES; i++) {
            modelViewMatrix.PushMatrix();
            //模型视图矩阵堆栈栈顶矩阵与随机球体矩阵相乘的结果放入栈顶
            modelViewMatrix.MultMatrix(spheres[i]);
            shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightEyePos, vSphereColor);
            //可与公转球体使用同一个容器类对象
            sphereBatch.Draw();
            
            modelViewMatrix.PopMatrix();
        }
        
        //设置甜甜圈平移距离(z轴负方向2.5)和旋转角度;
        modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);
        modelViewMatrix.PushMatrix();
        modelViewMatrix.Rotate(yRot, 0.0f, 0.1f, 0.0f);
        //使用点光源着色器渲染
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightEyePos, vTorusColor);
        torusBatch.Draw();
        modelViewMatrix.PopMatrix();
        
        //设置公转球体:反方向旋转,在x轴上平移0.8
        modelViewMatrix.Rotate(yRot *-2.0f, 0.0f, 1.0f, 0.0f);
        modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vSphereColor);
        sphereBatch.Draw();
        
        modelViewMatrix.PopMatrix();
        
        //后台渲染完成后交给前台
        glutSwapBuffers();
        //基于时间动画:实时刷新窗口
        glutPostRedisplay();
    }

    //图形定位

    void SetupRC()
    {
        //设置窗口背景颜色
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        //初始化管线控制器
        shaderManager.InitializeStockShaders();
        //开启深度测试:图形间重叠部分无须重复绘制
        glEnable(GL_DEPTH_TEST);
    
        //提交甜甜圈数据:三角形批次类对象、外圈半径、内圈半径、主半径三角形对数x、小半径三角形对数y(尽量:x=2*y,更圆滑)
        gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 15);
        //提交公转球体数据:三角形批次类对象、半径、底部到顶部三角形带的数量、一条三角形带中的三角形对数(一般指球体中间那条,为最大数)
        gltMakeSphere(sphereBatch, 0.1f, 26, 20);
    
        //线段模式,325个顶点
        floorBatch.Begin(GL_LINES, 325);
        for (GLfloat x = -20.0f; x <= 20.0f; x+=0.5f) {
            /*
             1.一个格子四个顶点,格子方向朝屏幕里面;
             2.只绘制x和z轴方向上的顶点;
             3.y轴坐标保持不变,负值,展示随机球体悬浮效果;
             */
            floorBatch.Vertex3f(x, -0.55f, 20.0f);
            floorBatch.Vertex3f(x, -0.55f, -20.0f);
            floorBatch.Vertex3f(20.0f, -0.55f, x);
            floorBatch.Vertex3f(-20.0f, -0.55f, x);
        }
        floorBatch.End();
    
        //随机悬浮球体:y值不变,x、z值随机
        for (int i = 0; i < NUM_SPHERES; i++) {
            GLfloat x = (GLfloat)(((rand()%400)-200)*0.1f);
            GLfloat z = (GLfloat)(((rand()%400)-200)*0.1f);
            spheres[i].SetOrigin(x, 0.0f, z);
        }
    }

    三、效果

     

    GitHub

    转载于:https://www.cnblogs.com/lybSkill/p/10021965.html

    展开全文
  • 球体贴图是老生常谈的东西了,很多时候都会遇到。选择什么方式去进行贴图,有时候也还是要考虑一番的。——ZwqXin.com第一次接触球体贴图这玩意,是课程的第三次作业的时候做的Demo(LostHeaven)。那时候恰逢汶川的...

    eb29f26e231013e01d82240dcea50bd4.png

    球体贴图是老生常谈的东西了,很多时候都会遇到。选择什么方式去进行贴图,有时候也还是要考虑一番的。——ZwqXin.com

    第一次接触球体贴图这玩意,是课程的第三次作业的时候做的Demo(LostHeaven)。那时候恰逢汶川的地震,自己就选择了那么个祈祷与人类破坏自然的主题,一开始的场景是一个下坠并“破碎”的地球。这个地球就是最初的我的球体贴图应用物了。怀念一下,贴图参考的是NEHE第二十多课那个,记不太清了,大致是直接用一张长方形纹理贴上去,然后设置一下纹理的生成方式(glTexGeni)之类的吧。其实哪怕是现在,这种贴图方式也是很平常的,就是Cylinder Map,把贴向一个柱体的纹理直接贴上球体上,让它包裹球体。确实简单,问题是球体的两极会因为过采样而出现褶皱。如果那两个点完全不暴露给观看者的话,那还好,不然就真的颇难看了。

    本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
    原文地址:http://www.zwqxin.com/archives/opengl/sphere-mapping-cubemap-stuff.html

    因为要考虑到贴到球体时的扭曲问题,赤道部分向两级的采样需求逐渐降低,所以那贴图一般都是中间“肥”上下两端“瘦”,呈现一定的扭曲,以尽量达到采样均匀,且贴到球体后看上去自然一点。对于两级的过采样问题,可以用一些方法降低采样率,具体不太懂所以就不多说了。针对CylinderMap的这些缺陷,部分人们开始选用CubeMap作为贴图方式。而本文也主要谈这种方式。

    关于CubeMapping:[Shader快速复习:Cube Mapping(立方环境贴图)]

    说到星体渲染,可能有人会知道Celestia这个软件,使用它可以渲染出一个绚烂的太空场景。这类软件可谓与球体贴图最靠近乎的东西之一了,从它对球体贴图方式的采用选择上看起吧:

    Creating Textures for Celestia

    上面这篇文章提及了主要使用的是Cylinder Map(至少在1.4版),而Cube Map作为一个“将来也许会支持”的选择项而被介绍。可见,Celestia应该还是比较偏好于前者的,这里面有两个比较重要的原因。

    1. 矩形的星体纹理,比起六张一体的立方纹理,较容易获得

    如果你在网上搜索一些星体的纹理,譬如地球啊、月球啊、火星啊,你搜到的基本都是一般的长方形纹理吧,配以分辨率(譬如4k纹理通常指长边至少为4000像素的纹理图)。所以,一般是很少见到原生的cubemap(6张图或dds文件)的。在著名的NASA分网站(http://earthobservatory.nasa.gov/)上,你可以搜到一堆堆的星体纹理,非常丰富,但大多都是基于一般的单一矩形纹理的:

    3fa518e2e3af269333498e47d64c3902.png

    通过一些工具,我们可以将这样的图片转换成6张子图,也就是把cylinderMap转换成CubeMap。Sourceforge项目“cubemap”(当前版本1.03)就是这样的工具之一,我就是使用它把上面一张2D纹理转换成6张纹理组成cubemap的,还算是比较方便的,效果也不错:

    52f70e4052ba31b167c22d0329730cfc.png

    所以说,虽然CubeMap的来源一般比较少,但动动手也是可以自己找素材做出来的。

    2.cubemap贴图的时候6张纹理在球体表面贴合处会出现缝迹

    如果说Cylinder贴图的弊端是两级位置的过采样造成的扭曲,那么Cube贴图的相应弊端就是接合处的欠采样造成的缝痕了。在这个论坛地址上可以看到一些截图。恰巧这个帖子也是针对这两种方法的讨论,建议看看。里面提及使用Cylinder贴图的同时使用VT来处理的方式,不过这对于我们来说实在也太specific了。

    一般来说,相对于cylinder贴图造成的那种“几公里外”也能看到的两级扭曲痛苦状,cubemap这种缝痕基本是不把眼睛贴向表面上都不会察觉的程度。贴到表面——这本身就有纹理本身欠采样造成的巨大锯齿在那里了——任何纹理都会这样,所以说CubeMap的这种问题在很多时候都可以忽略的。但是确实也有采用超高分辨率贴图,同时也允许观看者近距离靠近球体的场合,这时候这道缝就很成问题了。

    也是有对应的大致解决方案的,而且很简单。既然分别都是采样造成的问题,何不对应地在某些临界点改变一下采样率呢?对于Cylinder方式的贴图,在两级减少采样,这涉及采样规则方式的改变和效果的问题,临界点也很难界定,所以是很难做到的;而Cube方式的贴图,只要在边界处向相邻的纹理边界采样并混合(插值)一下,应该就能很好地拯救(模糊)那些缝痕。事实上,这甚至不用我们手动去搞,OpenGL3.2开始已经向我们提供了这么一个核心扩展了:seamless_cube_map

    在以前的GPU上是无法把纹理的filtering应用在cubemap相邻的两张子纹理上的。但既然如今可以做到,那么这个扩展就很自然出现的,只要在两纹理边界处像素线性插值一下,缝痕就基本消失了。当然开启这个扩展是会有点点影响效率的(毕竟采样工作增加了嘛),所以如果你确实没有需要近处去观摩一个cubemap(不限于球体贴图)的边缘,那就不要启用这个扩展了。

    事实上最好也要避免在运行渲染期间去切换这个OpenGL状态,很费效率。在初始化的时候设定,然后不要再去改变它——opengl的spec上如是说。设定很简单:

    C++代码 初始化阶段

    1. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

    以下是开启这个状态前后的程序截图,可见前者明显看到一条缝痕,后者基本看不到了:

    89d4293ad8de0dda88c508c3604d9714.png

    eb12a1d214dc780ba50999c15dc0d49a.png

    如果真的需要一个总结的话,我会说:是时候使用CubeMap来做一般的球面贴图了。

    本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明

    2011-10-4

    展开全文
  • 球体贴图是老生常谈的东西了,很多时候都会遇到。选择什么方式去进行贴图,有时候也还是要考虑一番的。——ZwqXin.com第一次接触球体贴图这玩意,是课程的第三次作业的时候做的Demo(LostHeaven)。那时候恰逢汶川的...
  • 现在画了一个球体,但是不知道怎样把一张世界地图的图片贴到他的表面上,希望有大神能帮帮我,谢谢你们了~!
  • Android OpenGL球体贴图

    千次阅读 2016-08-18 11:15:17
    OpenGL球体贴图的的整个流程就是计算出球体和纹理材质坐标,然后画出球体,按照纹理坐标将bitmap贴上去。 具体方法和上一篇文章画一个球体类似 OpenGL绘制球体 ,只是需要创建材质,并且需要构建一个用来渲染的...
  • 上一节我们学会了使用OpenGL着色器,但是在片段着色器中,我们使用简单纯色来绘制物体,这一节,我们要在片段着色器中使用采用器对纹理进行采样输出,作为物体表面的颜色,进而绘制带有纹理贴图的物体。纹理纹理简单...
  • OpengL球体跳跃前进例子

    千次阅读 2014-08-27 23:52:44
    #include #include "gl/glut.h" #include #include #include // 参数指定正方形的位置和大小 float xsite = 100.0; //圆心坐标 float ysite = 200.0;...GLsizei rsize = 20;...float ystep = 0.0
  • opengl球体 环境映射很正常 但纹理映射贴不上去 用的是直接画球函数glutsolidphere(1,100,100); 茶壶的环境映射,纹理映射都可以正常画出;长方体给了纹理坐标也正常。 球体的是不是也要给纹理坐标啊? ...
  • OpenGL绘制球体

    2018-11-06 01:06:04
    OpenGL绘制球体
  • 易语言OpenGL控制球体源码,OpenGL控制球体,建立OPenGL组件,撤消OPenGL组件,框架初始化,绘图,画图,按键
  • OpenGL控制球体.rar

    2020-04-05 07:20:20
    OpenGL控制球体.rar
  • OpenGL 建模球体

    2009-11-29 00:03:55
    通过OpenGL基本体素,例如三角形、三角形带、四边形、四边形带,它们都可以构成的球体。通过改变半径控制大小,通过改变角度的改变大小就可以改变顶点的数目和密度,通过在调用回调函数设置模式,就可以改变填充状态...
  • qt opengl球体

    千次阅读 2018-09-15 13:41:57
    和一般写opengl的程序一样,就直接出代码不多说。  在qt中我使用qopenglwidget来操作opengl程序,声明如下 #ifndef WIDGET_H #define WIDGET_H #include &lt;QOpenGLWidget&gt; #include "...
  • opengl 立体球体的实现

    2012-12-23 08:56:36
    1. 利用GLUT库,编写一个OpenGL程序,实现以下功能:  仿照课本的例子,绘制若干OpenGL基本体素(三角形、三角形带、四边形、四边 形带)构成的球体,  可以控制改变球的数量和球的体积,来改变基本体素的数量...
  • Android OpenGL绘制球体

    千次阅读 2016-08-16 18:01:52
    opengl画球~~_(:зゝ∠)_
  • OpenGL 旋转球体

    千次阅读 2011-05-24 15:43:00
    #include GLfloat X = 10.0f; GLfloat Y = 1.0f; GLfloat Z = 5.0f; void myDisplay(void) { GLfloat diffuse[] = {0.7,0.7,0.0,1.0}; glClear (GL_COLOR_BUFFER_BIT); glColor3f(1.0,1.0,1.0...
  • C#+OpenGL绘制球体

    2017-06-22 15:16:11
    用VS2012编写
  • 真实感球体绘制 opengl

    2021-04-07 10:49:16
    真实感球体绘制 opengl
  • 基于MFC的opengl球体

    2011-07-17 19:27:11
    基于MFC的opengl绘图 利用顶点数组绘成圆球;简单的openGL应用,适合初学者学习;Application of openGL C++,MFC tec
  • 今天用opengl建模了一个球体,接下来简单的介绍一下自己的实现方法。 先用一张比较容易理解的图来说明。 如图所示,假设要建模一个单位球体,球上任意一点的坐标都可由图中所示公式表示。 接下来的代码将生成15...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 550
精华内容 220
关键字:

opengl球体