OpenGLES系列demo之(一):绘制三角形

        在上一篇文章 OpenGLES系列demo之框架简介 (后文简称“框架文章”)中,我们先介绍了框架,本文基于这个框架上,简述使用openGL ES绘制一个三角形的大致步骤。

一、绘制三角形的步骤

        绘制三角形的一般步骤如下:

  1. 创建 OpenGLES 环境(可以借助于 GLSurfaceView 创建的上下文对象);
  2. 编译并链接着色器程序;
  3. 指定着色器程序,为着色器程序中的变量赋值;
  4. 绘制。

二、创建OpenGLES环境

        这个创建在上一篇框架文章中搭建的框架基本上已经实现了openGLES环境,这里我们再简单过一下。

        1、简单自定义GLSurfackView。-- 参考“框架文章”中的MyGLSurfaceView;

        2、自定义Render实现GLSurfaceView.Renderer接口。 -- 参考“框架文章”中的MyGLRender;

        以上两步基本就创建好了openGLES环境,

        3、由于我们在c++层完成绘制,因此还需要与jni的一些接口调用。 -- 参考“框架文章”中的MyNativeRender等;

三、编译链接着色器程序,实现绘制类

        以下部分我们是在c++层去操作,实现绘制。

1、编译和链接着色器程序的类

        在我们的“框架文章”中,已经讲到将编译和绘制着色器相关的东西,提出到一个工具类GLUtils,这个类是通用的,实现编译和链接着色器程序等功能。这里不再赘述,看参考“框架”文章。

2、三角形的绘制实现类

        这个便是本文的重点,在框架的基础上,每个demo最重要的区别就是这里。在这个三角形的绘制实现类TriangleSample中,我们会实现三角形的绘制。包括它的顶点着色器等等的定义。

        三角形的顶点着色器脚本:

#version 300 es                          
layout(location = 0) in vec4 vPosition;  
void main()                              
{                                        
   gl_Position = vPosition;              
}                                        

        片元着色器脚本:

#version 300 es                              
precision mediump float;                     
out vec4 fragColor;                          
void main()                                  
{                                            
   fragColor = vec4 ( 0.0, 0.0, 1.0, 1.0 );  //填充三角形区域为蓝色
}                                            

        这两个脚本我们定义到字符串数组后,在绘制类的Init初始化函数中调用GLUtils工具类的创建程序进行相关绑定,如下:

void TriangleSample::Init()
{
	if(m_ProgramObj != 0)
		return;
	char vShaderStr[] =
			"#version 300 es                          \n"
			"layout(location = 0) in vec4 vPosition;  \n"
			"void main()                              \n"
			"{                                        \n"
			"   gl_Position = vPosition;              \n"
			"}                                        \n";

	char fShaderStr[] =
			"#version 300 es                              \n"
			"precision mediump float;                     \n"
			"out vec4 fragColor;                          \n"
			"void main()                                  \n"
			"{                                            \n"
			"   fragColor = vec4 ( 0.0, 0.0, 1.0, 1.0 );  \n"
			"}                                            \n";

	m_ProgramObj = GLUtils::CreateProgram(vShaderStr, fShaderStr, m_VertexShader, m_FragmentShader);

}

        先来看下opengles 坐标系中三角形顶点坐标:

        接下来在Draw函数中指定着色器程序,为着色器程序中的变量赋值,传入顶点坐标信息,然后绘制三角形。如下:

void TriangleSample::Draw(int screenW, int screenH)
{
	LOGCATE("TriangleSample::Draw");
	GLfloat vVertices[] = {
			0.0f,  0.5f, 0.0f,
			-0.5f, -0.5f, 0.0f,
			0.5f, -0.5f, 0.0f,
	};

	if(m_ProgramObj == 0)
		return;

	glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(1.0, 1.0, 1.0, 1.0);

	// Use the program object
	glUseProgram (m_ProgramObj);

	// Load the vertex data
	glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
	glEnableVertexAttribArray (0);

	glDrawArrays (GL_TRIANGLES, 0, 3);
	glUseProgram (GL_NONE);

}

        三角形的实现绘制类TriangleSample中最重要就是这两个函数,初始化和绘制。

        它们的调用是在MyGLRenderContext类中调用,并提高给JNI,最终到java层去调用。

MyGLRenderContext::MyGLRenderContext()
{
	m_pCurSample = new TriangleSample();
	m_pBeforeSample = nullptr;

}

MyGLRenderContext::~MyGLRenderContext()
{
	if (m_pCurSample)
	{
		delete m_pCurSample;
		m_pCurSample = nullptr;
	}

	if (m_pBeforeSample)
	{
		delete m_pBeforeSample;
		m_pBeforeSample = nullptr;
	}

}

void MyGLRenderContext::OnSurfaceCreated()
{
	LOGCATE("MyGLRenderContext::OnSurfaceCreated");
	glClearColor(1.0f,1.0f,1.0f, 1.0f);
}

void MyGLRenderContext::OnSurfaceChanged(int width, int height)
{
	LOGCATE("MyGLRenderContext::OnSurfaceChanged [w, h] = [%d, %d]", width, height);
	glViewport(0, 0, width, height);
	m_ScreenW = width;
	m_ScreenH = height;
}

void MyGLRenderContext::OnDrawFrame()
{
	LOGCATE("MyGLRenderContext::OnDrawFrame");
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

	if (m_pBeforeSample)
	{
		m_pBeforeSample->Destroy();
		delete m_pBeforeSample;
		m_pBeforeSample = nullptr;
	}

	if (m_pCurSample)
	{
		m_pCurSample->Init();
		m_pCurSample->Draw(m_ScreenW, m_ScreenH);
	}
}

        到这里demo基本就做完了。

四、运行demo

        运行一下demo,可以看到效果如下:

         该demo已放到github上,有需要的可以下载看看:

https://github.com/weekend-y/openGL_Android_demo/tree/master/OpenGL_Triangle

猜你喜欢

转载自blog.csdn.net/weekend_y45/article/details/126049912
今日推荐