第一部分概念

OpenGL 坐标系统:OpenGL 坐标系中每个顶点的 x,y,z 坐标都应该在 -1.0 到 1.0 之间,超出这个坐标范围的顶点都将不可见。将一个物体(图像)渲染到屏幕上,通常经过将物体坐标转换为标准化设备坐标,然后再将标准化设备坐标转化为屏幕坐标的过程。

**物体显示:**该过程通常涉及多个坐标系统的变换,将所有顶点转换为片段之前,顶点需要处于不同的坐标系统进行计算,对我们来说比较重要的有 5 个坐标系统:

局部空间:是指对象所在的空间,原点由自己定义,模型的所有顶点对于你的对象来说都是局部的。

世界空间:它可以实现物体的平移,缩放,旋转等操作,就是将他们放在我们指定位置。这些变换是通过模型矩阵(Model Matrix)实现的。在 C/C++ 中可以利用 GLM 构建模型矩阵(直接百度下载开源库,只用把头文件文件夹放入到工程中,进行引用就可以使用了)

glm::mat4 Model = glm::mat4(1.0f); //单位矩阵
Model = glm::scale(Model, glm::vec3(2.0f, 2.0f, 2.0f)); //缩放
Model = glm::rotate(Model, MATH_PI/2, glm::vec3(1.0f, 0.0f, 0.0f)); //沿 x 轴旋转 90 度
Model = glm::translate(Model, glm::vec3(0.0f, 1.0f, 0.0f)); //沿 y 轴正方向平移一个单位

观察空间:称为OpenGL相机空间,就是从摄像机的角度观察得到的空间,他将对象的世界坐标转换为观察者视野前面的坐标,通常可以由一系列的平移和旋转来实现这种方式将对象移到摄像机面前。

// View matrix
glm::mat4 View = glm::lookAt(glm::vec3(0, 0, 3), // Camera is at (0,0,1), in World Space 相机位置glm::vec3(0, 0, 0), // and looks at the origin 观察点坐标glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down) 相机 up 方向,即相机头部朝向
);

裁剪空间:用来裁剪观察对象的空间,在顶点着色器运行的最后,OpenGL期望所有的坐标都能落在一个给定的范围内,则这个范围外的点需要被裁剪掉。

  • 投影矩阵**:用来将顶点坐标从观察空间转换到裁剪空间,投影矩阵分为正交投影,透视投影

前两个参数指定了平截头体的左右坐标,
第三和第四参数指定了平截头体的底部和上部。通过这四个参数我们定义了近平面和远平面的大小,
然后第五和第六个参数则定义了近平面和远平面的距离。这个指定的投影矩阵将处于这些 x,y,z 范围之间的坐标转换到标准化设备坐标系中。
glm::mat4 Projection = glm::ortho(-ratio, ratio, -1.0f, 1.0f, 0.0f, 100.0f); //ratio 一般表示视口的宽高比,width/height

第一个参数定义了 fov 的值,它表示的是视野(Field of View),并且设置了观察空间的大小。对于一个真实的观察效果,它的值经常设置为 45.0,但想要看到更多结果你可以设置一个更大的值。
第二个参数设置了宽高比,由视口的高除以宽。
第三和第四个参数设置了平截头体的近和远平面。我们经常设置近距离为 0.1 而远距离设为 100.0 。所有在近平面和远平面的顶点且处于平截头体内的顶点都会被渲染。
glm::mat4 Projection = glm::perspective(45.0f, ratio, 0.1f, 100.f); //ratio 一般表示视口的宽高比,width/height,

整个坐标系统的变换矩阵可以用一个矩阵表MVPMatrix = Projection * View * Model

第二部分实践

工程包名

com.example.basiclighting8code

实现 OpenGL 3D 效果最简单的方式是在顶点着色器中将顶点坐标与 MVP 变换矩阵相乘:

java代码和环境部分与之前学习到的opengl显示图片的工程代码是一致的,但是可以引入通过触屏来改变图片位置的参数,从而更形象。C++部分只有顶点的shader不一样,还有在绘画的时候需要对顶点着色器里面的uniform mat4 u_MVPMatrix;//变化矩阵进行设置。

1)C++部分

顶点着色器

#version 300 es
layout (location = 0) in vec4 a_position;
layout (location = 1) in vec2 a_texCoord;
uniform mat4 u_MVPMatrix;//变化矩阵
out vec2 v_texCoord;void main()
{gl_Position = u_MVPMatrix * a_position;v_texCoord = a_texCoord;
}

片段着色器

#version 300 es
precision mediump float;
layout(location = 0) out vec4 outColor;
in vec2 v_texCoord;
uniform sampler2D s_TextureMap;
void main()
{outColor = texture(s_TextureMap, v_texCoord);
}

NativeGL.cpp

//
// Created by CreatWall_zhouwen on 2023/4/11.
//#include "jni.h"
#include <android/log.h>
#include <GLES2/gl2.h>
#include "Util.h"
#include "CoordSystem.h"
#include "ReadFileUtil.h"
#define NATIVE_RENDER_CLASS_NAME "com/example/basiclighting8code/NativeImpl"
#define TAG "GLTRIANGLE"
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_example_sevencoordsystem_NativeImpl* Method:    NativeImpl_InitScene* Signature: (Ljava/lang/Object;)V*/
JNIEXPORT void JNICALL NativeImpl_InitScene(JNIEnv *env, jobject instance, jobject msg)
{g_mrg = AAssetManager_fromJava(env, msg);
}/** Class:     com_example_sevencoordsystem_NativeImpl* Method:    init* Signature: ()V*/
JNIEXPORT void JNICALL NativeImpl_init(JNIEnv *env, jobject instance)
{CoordSystem::GetInstance();int width = 0, height = 0;unsigned char *img = ReadBMP("awesomeface.bmp", width, height);CoordSystem::GetInstance()->getTexturedata(img, width, height);CoordSystem::GetInstance()->CreateProgram(reinterpret_cast<const char *>(LoadFileContent("vertex.vs")),reinterpret_cast<const char *>(LoadFileContent("fShader.fs")));
}/** Class:     com_example_twodrawtexture_NativeImpl* Method:    OnSurfaceChanged* Signature: (II)V*/
JNIEXPORT void JNICALL NativeImpl_OnSurfaceChanged(JNIEnv *env, jobject instance, jint width, jint height)
{glViewport(0, 0, width, height);CoordSystem::GetInstance()->OnSurfaceChanged(width, height);
}/** Class:     com_example_twodrawtexture_NativeImpl* Method:    OnSurfaceChanged* Signature: (FFFF)V*/
JNIEXPORT void JNICALL native_UpdateTransformMatrix(JNIEnv *env, jobject instance, jfloat rotateX, jfloat rotateY, jfloat scaleX, jfloat scaleY)
{//通过这个方法来改变图片的坐标CoordSystem::GetInstance()->UpdateTransformMatrix(rotateX, rotateY, scaleX, scaleY);
}/** Class:     com_example_twodrawtexture_NativeImpl* Method:    draw* Signature: ()V*/
JNIEXPORT void JNICALL NativeImpl_draw(JNIEnv *env, jobject instance)
{CoordSystem::GetInstance()->Draw();
}#ifdef __cplusplus
}
#endifstatic JNINativeMethod g_RenderMethods[] = {{"NativeImpl_InitScene",             "(Ljava/lang/Object;)V",       (void *)(NativeImpl_InitScene)},{"NativeImpl_init",             "()V",       (void *)(NativeImpl_init)},{"NativeImpl_OnSurfaceChanged",   "(II)V",     (void *)(NativeImpl_OnSurfaceChanged)},{"NativeImpl_draw",        "()V",       (void *)(NativeImpl_draw)},{"native_UpdateTransformMatrix",        "(FFFF)V",       (void *)(native_UpdateTransformMatrix)},
};static int RegisterNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodNum)
{LOGD("RegisterNativeMethods");jclass clazz = env->FindClass(className);if (clazz == NULL){LOGD("RegisterNativeMethods fail. clazz == NULL");return JNI_FALSE;}if (env->RegisterNatives(clazz, methods, methodNum) < 0){LOGD("RegisterNativeMethods fail");return JNI_FALSE;}return JNI_TRUE;
}static void UnregisterNativeMethods(JNIEnv *env, const char *className)
{LOGD("UnregisterNativeMethods");jclass clazz = env->FindClass(className);if (clazz == NULL){LOGD("UnregisterNativeMethods fail. clazz == NULL");return;}if (env != NULL){env->UnregisterNatives(clazz);}
}// call this func when loading lib
extern "C" jint JNI_OnLoad(JavaVM *jvm, void *p)
{LOGD("===== JNI_OnLoad =====");jint jniRet = JNI_ERR;JNIEnv *env = NULL;if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK){return jniRet;}jint regRet = RegisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME, g_RenderMethods,sizeof(g_RenderMethods) /sizeof(g_RenderMethods[0]));if (regRet != JNI_TRUE){return JNI_ERR;}return JNI_VERSION_1_6;
}extern "C" void JNI_OnUnload(JavaVM *jvm, void *p)
{JNIEnv *env = NULL;if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK){return;}UnregisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME);
}

CoordSystem.h

//
// Created by CreatWall_zhouwen on 2023/4/13.
//#ifndef TWODRAWTEXTURE_TEXTUREDEMO_H
#define TWODRAWTEXTURE_TEXTUREDEMO_H#include <GLES3/gl3.h>
#include <detail/type_mat.hpp>
#include <detail/type_mat4x4.hpp>
#define MATH_PI 3.1415926535897932384626433832802
class CoordSystem {
public:CoordSystem(){program = 0;vertexShaderHandle = 0;fragShaderHandle = 0;};~CoordSystem(){};void CreateProgram(const char *ver, const char *frag);void Draw();void getTexturedata(unsigned char *data, int width, int height);static CoordSystem* GetInstance();static void DestroyInstance();void OnSurfaceChanged(int width, int height);void UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY);void UpdateMVPMatrix(glm::mat4 &mvpMatrix, int angleX, int angleY, float ratio);
private:GLuint program;GLuint vertexShaderHandle;GLuint fragShaderHandle;GLuint m_VaoId;//存放顶点数据GLuint m_VboIds[3];//0表示顶点坐标缓冲区,1表示离屏渲染纹理坐标缓冲区,2表示纹理索引坐标缓冲区unsigned int m_TextureId;unsigned char *texturedata;int texturewidth, textureheight;int srceenWidth, srceenHeight;//屏幕宽高GLint m_SamplerLoc;GLint m_MVPMatLoc;glm::mat4 m_MVPMatrix;int m_AngleX;int m_AngleY;float m_ScaleX;float m_ScaleY;
};#endif //TWODRAWTEXTURE_TEXTUREDEMO_H

CoordSystem.cpp

//
// Created by CreatWall_zhouwen on 2023/4/13.
//#include "CoordSystem.h"
#include "Util.h"
#include "GLUtil.h"
#include <gtc/matrix_transform.hpp>
CoordSystem* m_pContext = nullptr;
#define TAG "DRAWTEXTURE"float vertices[] = {-1.0f, -1.0f, 0.0f,1.0f, -1.0f, 0.0f,-1.0f,  1.0f, 0.0f,1.0f,  1.0f, 0.0f,
};
//纹理坐标
GLfloat vTexCoors[] = {0.0f, 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f,
};
//索引数组
unsigned int indices[] = {0, 1, 2, 1, 3, 2
};void CoordSystem::CreateProgram(const char *ver, const char *frag)
{LOGD("CreateProgram Enter");// 编译链接用于离屏渲染的着色器程序program = CreateGLProgram(ver, frag, vertexShaderHandle, fragShaderHandle);if (program == GL_NONE){LOGD("FBOSample::Init m_ProgramObj == GL_NONE");return;}LOGD("CreateGLProgram Success");m_SamplerLoc = glGetUniformLocation(program, "s_TextureMap");m_MVPMatLoc = glGetUniformLocation(program, "u_MVPMatrix");/* -----顶点相关------ */glGenBuffers(4, m_VboIds);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[1]);glBufferData(GL_ARRAY_BUFFER, sizeof(vTexCoors), vTexCoors, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[2]);//最后一个为纹理的索引缓冲数据glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);LOGD("glGenBuffers Success");glGenVertexArrays(1, &m_VaoId);//初始化离屏渲染的VAOglBindVertexArray(m_VaoId);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const void *)0);glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[1]);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const void *)0);glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[2]);glBindVertexArray(GL_NONE);LOGD("m_VaoIds[1] Success");/* -----创建加载纹理------ *///创建纹理glGenTextures(1, &m_TextureId);//将纹理绑定到GL_TEXTURE_2DglBindTexture(GL_TEXTURE_2D, m_TextureId);//为当前绑定的纹理对象设定纹理环绕方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//重复纹理的填充方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//为当前绑定的纹理对象设定纹理过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//缩小时线性插值glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//放到就是线性//绑定纹理数据glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texturewidth, textureheight, 0, GL_RGB, GL_UNSIGNED_BYTE, texturedata);LOGD("CreateProgram %s", texturedata);glGenerateMipmap(GL_TEXTURE_2D);//为当前绑定的纹理自动生成所有需要的多级渐远纹理LOGD("CreateProgram END");
}
void CoordSystem::Draw()
{glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);glClearColor(0.2f, 0.9f, 0.3f, 1.0f);UpdateMVPMatrix(m_MVPMatrix, m_AngleX, m_AngleY, (float)srceenWidth / srceenHeight);glUseProgram (program);glBindVertexArray(m_VaoId);glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);// Bind the RGBA map//glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_TextureId);glUniform1i(m_SamplerLoc, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const void *)0);glBindVertexArray(0);}
CoordSystem* CoordSystem::GetInstance()
{if (m_pContext == nullptr){m_pContext = new CoordSystem();}return m_pContext;
}
void CoordSystem::DestroyInstance()
{if (m_pContext){delete m_pContext;m_pContext = nullptr;}
}void CoordSystem::getTexturedata(unsigned char *data, int width, int height)
{texturedata = data;texturewidth = width;textureheight = height;
}void CoordSystem::OnSurfaceChanged(int width, int height) {glViewport(0, 0, width, height);srceenWidth = width;srceenHeight = height;
}
/*** @param angleX 绕X轴旋转度数* @param angleY 绕Y轴旋转度数* @param ratio 宽高比* */
void CoordSystem::UpdateMVPMatrix(glm::mat4 &mvpMatrix, int angleX, int angleY, float ratio)
{LOGD("CoordSystemSample::UpdateMVPMatrix angleX = %d, angleY = %d, ratio = %f", angleX, angleY, ratio);angleX = angleX % 360;angleY = angleY % 360;//转化为弧度角float radiansX = static_cast<float>(MATH_PI / 180.0f * angleX);float radiansY = static_cast<float>(MATH_PI / 180.0f * angleY);// Projection matrix//glm::mat4 Projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 100.0f);//glm::mat4 Projection = glm::frustum(-ratio, ratio, -1.0f, 1.0f, 4.0f, 100.0f);glm::mat4 Projection = glm::perspective(45.0f,ratio, 0.1f,100.f);// View matrixglm::mat4 View = glm::lookAt(glm::vec3(0, 0, 4), // Camera is at (0,0,1), in World Spaceglm::vec3(0, 0, 0), // and looks at the originglm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down));// Model matrixglm::mat4 Model = glm::mat4(1.0f);Model = glm::scale(Model, glm::vec3(m_ScaleX, m_ScaleY, 1.0f));//缩放Model = glm::rotate(Model, radiansX, glm::vec3(1.0f, 0.0f, 0.0f));Model = glm::rotate(Model, radiansY, glm::vec3(0.0f, 1.0f, 0.0f));Model = glm::translate(Model, glm::vec3(0.0f, 0.0f, 0.0f));mvpMatrix = Projection * View * Model;for (int i = 0; i < 4; ++i) {LOGD("CoordSystemSample::UpdateMVPMatrix angleX = %f %f %f %f",mvpMatrix[i][0],mvpMatrix[i][1],mvpMatrix[i][2],mvpMatrix[i][3]);}}void CoordSystem::UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY) {m_AngleX = static_cast<int>(rotateX);m_AngleY = static_cast<int>(rotateY);m_ScaleX = scaleX;m_ScaleY = scaleY;
}

2) Java部分

MyGLSurfaceView.java

package com.example.basiclighting8code;import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;public class MyGLSurfaceView extends GLSurfaceView implements ScaleGestureDetector.OnScaleGestureListener{private MyRenderer renderer;private AssetManager mrg;private final float TOUCH_SCALE_FACTOR = 180.0f / 320;private float mPreviousY;private float mPreviousX;private int mXAngle;private int mYAngle;private int mRatioWidth = 0;private int mRatioHeight = 0;private ScaleGestureDetector mScaleGestureDetector;private float mPreScale = 1.0f;private float mCurScale = 1.0f;private long mLastMultiTouchTime;public MyGLSurfaceView(Context context) {super(context);mrg = getResources().getAssets();setEGLContextClientVersion(3);setEGLConfigChooser(8, 8, 8, 8, 16, 8);renderer = new MyRenderer();setRenderer(renderer);setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);mScaleGestureDetector = new ScaleGestureDetector(context, this);}//屏幕触摸事件public boolean onTouchEvent(MotionEvent e) {if (e.getPointerCount() == 1) {consumeTouchEvent(e);long currentTimeMillis = System.currentTimeMillis();if (currentTimeMillis - mLastMultiTouchTime > 200) {float y = e.getY();float x = e.getX();switch (e.getAction()) {case MotionEvent.ACTION_MOVE:float dy = y - mPreviousY;float dx = x - mPreviousX;mYAngle += dx * TOUCH_SCALE_FACTOR;mXAngle += dy * TOUCH_SCALE_FACTOR;}mPreviousY = y;mPreviousX = x;//更新xy的角度renderer.updateTransformMatrix(mXAngle, mYAngle, mCurScale, mCurScale);requestRender();}else {mScaleGestureDetector.onTouchEvent(e);}}return true;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);if (0 == mRatioWidth || 0 == mRatioHeight) {setMeasuredDimension(width, height);} else {if (width < height * mRatioWidth / mRatioHeight) {setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);} else {setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);}}}public void setAspectRatio(int width, int height) {if (width < 0 || height < 0) {throw new IllegalArgumentException("Size cannot be negative.");}mRatioWidth = width;mRatioHeight = height;requestLayout();}public void consumeTouchEvent(MotionEvent e) {dealClickEvent(e);float touchX = -1, touchY = -1;switch (e.getAction()) {case MotionEvent.ACTION_MOVE:touchX = e.getX();touchY = e.getY();break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:touchX = -1;touchY = -1;break;default:break;}//滑动、触摸/*switch (mGLRender.getSampleType()) {case SAMPLE_TYPE_KEY_SCRATCH_CARD:mGLRender.setTouchLoc(touchX, touchY);requestRender();break;default:break;}*///点击switch (e.getAction()) {case MotionEvent.ACTION_MOVE://touchX = e.getX();//touchY = e.getY();break;case MotionEvent.ACTION_UP:break;case MotionEvent.ACTION_CANCEL:break;default:break;}}public void dealClickEvent(MotionEvent e) {float touchX = -1, touchY = -1;switch (e.getAction()) {case MotionEvent.ACTION_UP:touchX = e.getX();touchY = e.getY();break;default:break;}}@Overridepublic boolean onScale(ScaleGestureDetector detector) {float preSpan = detector.getPreviousSpan();float curSpan = detector.getCurrentSpan();if (curSpan < preSpan) {mCurScale = mPreScale - (preSpan - curSpan) / 200;} else {mCurScale = mPreScale + (curSpan - preSpan) / 200;}mCurScale = Math.max(0.05f, Math.min(mCurScale, 80.0f));renderer.updateTransformMatrix(mXAngle, mYAngle, mCurScale, mCurScale);requestRender();return false;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {return false;}@Overridepublic void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {mPreScale = mCurScale;mLastMultiTouchTime = System.currentTimeMillis();}private class MyRenderer implements Renderer {@Overridepublic void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {NativeImpl.NativeImpl_InitScene(mrg);NativeImpl.NativeImpl_init();}@Overridepublic void onSurfaceChanged(GL10 gl10, int width, int height) {NativeImpl.NativeImpl_OnSurfaceChanged(width, height);}@Overridepublic void onDrawFrame(GL10 gl10) {NativeImpl.NativeImpl_draw();}public void updateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY){NativeImpl.native_UpdateTransformMatrix(rotateX, rotateY, scaleX, scaleY);}}
}

十一、OpenGL的坐标系统相关推荐

  1. 【Modern OpenGL】坐标系统 Coordinate Systems

    说明:跟着learnopengl的内容学习,不是纯翻译,只是自己整理记录. 强烈推荐原文,无论是内容还是排版. 原文链接 本文地址: http://blog.csdn.net/aganlengzi/a ...

  2. win32下的OpenGL绘图环境框架

    Win32下OpenGL入门 主要的步骤包括:添加opengl头文件,库文件,键盘鼠标响应,像素格式设置,opengl环境初始化,绘图变量设置,创建窗口,窗口大小改变时响应,绘制场景,源文件 1, 新 ...

  3. 实验1 OpenGL初识

    一.实验目的 熟悉编程环境:了解光栅图形显示器的特点:了解计算机绘图的特点: 利用VC+OpenGL作为开发平台设计程序,以能够在屏幕上生成任意一个像素点作为本实验的目标. 二.实验内容 了解和使用V ...

  4. Android Studio OpenGL ES绘制三棱锥/四面体的多纹理贴图 每个面使用一张图片渲染

    本文参考了王刚的<疯狂Android讲义(第3版)>P554-P559 要求:利用OpenGL ES绘制一个三棱锥,并对每个面进行纹理贴图,每个面使用不同的图片进行渲染. 环境:Andro ...

  5. OpenGL ES EGL 简介

    目录 一.EGL 简介 二.EGL 跨平台之 ANGLE 1.ANGLE 支持跨平台 2.ANGLE 支持渲染器 3.ANGLE 下载地址 三.EGL 坐标系 四.EGL 绘图步骤 五.猜你喜欢 零基 ...

  6. java3d lookat_基于 OpenGL 进行 3D 图形开发

    3D 开发的一般思路转自:http://www.linuxgraphics.cn/graphics/opengl_dev_summary.html 3D 开发主要分为三个步骤:建模.渲染.逻辑控制. ...

  7. Win32 OpenGL编程(4) 2D图形基础(颜色及坐标体系进阶知识)

    Win32 OpenGL 编程 (4) 2D 图形基础(颜色及坐标体系进阶知识) write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 ...

  8. OpenGL渲染管线解析

    背景: 本篇文章主要偏向理论知识的讲解,实践方面后期会进行讲解.opengl的渲染管线中,如果接触3D渲染不多情况下,比如经常做视频滤镜或视频渲染显示的话,经常接触的两个部分就是顶点着色器.片段着色器 ...

  9. gnuplot画图命令_Gnuplot科学绘图(二十六)——image 绘图

    Gnuplot科学绘图系列内容Gnuplot科学绘图(二十一)--简单 3D 函数绘图Gnuplot科学绘图(二十二)--数据文件存储格式Gnuplot科学绘图(二十三)-- 3D 数据曲面绘图及边框 ...

最新文章

  1. 力扣(LeetCode)刷题,简单+中等题(第28期)
  2. ASP.NET防伪令牌与JSON有效载荷
  3. 【数理知识】《积分变换与场论》王振老师-第1章-傅里叶变换
  4. centos 程序 mysql数据库文件位置,CentOS 更改MySQL数据库目录位置
  5. 【渝粤教育】电大中专电子商务网站建设与维护 (11)作业 题库
  6. pip升级python包命令_python安装扩展库常用的是什么工具
  7. BethuneX:DBA最信赖的监控和智能巡检平台
  8. MySQL : mysql连接报 Communications link failure
  9. html中的a标签、img标签、iframe标签、列表标签
  10. jQuery DataTables 插件使用笔记
  11. python描述对象静态特性的数据为_对于需要几个单位共同负担的一张原始凭证上的支出,应根据其他单位负担部分为其提高( )。...
  12. iOS 视频转gif
  13. pytest 测试框架学习(14):pytest.warns
  14. UVA - 10158 War
  15. 编辑距离(Edit Distance) 一文读懂(Python实现)
  16. 选择SaaS供应商的15个关键问题
  17. 清华大学环境工程专业考研经验分享
  18. 命令行窗口快速复制粘贴的方法
  19. 表格的编辑插件 editable.js
  20. 基于javaweb的毕业设计毕业论文管理系统(java+ssm+jsp+tomcat+mysql)

热门文章

  1. 如何加强仓储货架的安全性架设?
  2. 智慧党建系统源码,便利党务工作安排保护数据安全
  3. 基于多目标灰狼算法的冷热电联供型微网低碳经济调度(Matlab代码实现)
  4. fluxion部分功能的使用
  5. linux wifi tool,fluxion linux tool for wifi
  6. 百度智能车竞赛丝绸之路1——智能车设计与编程实现控制
  7. BTchat链语社交软件 重新定义你的私密社交
  8. 恶意软件攻破网络防御措施的5种方式揭秘!网警教你如何抵御!
  9. 【JavaScript高级05】JavaScript第二大神兽:闭包
  10. Linux C 数据结构---链表(单向链表)