买了人民邮电计算机图形学实用教程,但是一直懒得看,现在决定利用CSDN博客平台来督促自己。
上网搜了下,大多数人都是用老式的固定管线,没看到有谁用现代OpenGL,看了算法实现,尝试改成着色器的,结果发现很多博客里面算法实现貌似有问题,还是自己看教材吧,教材上的算法写得很清楚了,一步一步实现即可。
刚买到苏小红教授主编的这本图形学实用教程的时候,看到SetPixel函数我就晕菜了,搞坨不清是咋回事,后来才知道SetPixel是windows下的函数,看了其他人博客里面用固定管线实现其实很简单,就是调用glBegin(GL_POINTS); glVertex2i(x,y)。
改成着色器很简单,代码是我学习learnopengl的时候拿自己整的工程改的。DDA法和中点画线法.
DDA数值微分画线算法:
教材里面的算法x的增量是1,但是OpenGL里面标准化设备坐标是一个x、y和z值在-1.0到1.0的一小段空间,所以我把增量改成0.1,还可以更小。
运行结果:
void bges::CGfxRenderDDADrawLine::startUp()
{
vertexArrayID = 0;
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
// Create and compile our GLSL program from the shaders
Shader shader;
programID =shader.LoadShaders("/home/study/learnopengl/MyProject/shaderFile/SimpleVertexShader.vertexshader","/home/study/learnopengl/MyProject/shaderFile/SimpleFragmentShader.fragmentshader" );
static GLfloat lineVertex_Buffer_Data[292] = {0.0};
//{0.00000,1.000000,0.250000,0.500000};
this->length = GetLineDDAData(-1.0,0.0,0.45,0.41,lineVertex_Buffer_Data);
static GLfloat lineVertexX[13] = {0.0};
static GLfloat lineVertexY[13] = {0.0};
vertexbuffer = 0;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(lineVertex_Buffer_Data),
lineVertex_Buffer_Data, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,(void*)0);
}
int bges::CGfxRenderDDADrawLine::GetLineDDAData(float x1,float y1,float x2,float y2, GLfloat vertex_buffer_data[])
{
int length = 0,k = 0;
float x = x1;
float y = y1;
float dx = abs(x2 - x1);
float dy = abs(y2 - y1);
float m = dy / dx;
length = dx - dy >= 0 ? dx : dy;
int yinit = length / 0.01;
vertex_buffer_data[ k ] = x;
vertex_buffer_data[ k + yinit ] = y;
//printf("%f,%f\n",x,y);
//vertex_buffer_data[ k + 2 ] = 0.0f;
k = 1;
for(int i = 1;i < yinit;i++){
if(dx - dy > 0 && x1 - x2 < 0.0){
x += 0.1;
y += m;
vertex_buffer_data[ k ] = x;
vertex_buffer_data[ k + yinit ] = y;
//vertex_buffer_data[ k + 2 ] = 0.0f;
printf("%f,%f\n",x,y);
k++;
}
}
return length / 0.1;
}
渲染也很简单
void bges::CGfxRenderDDADrawLine::Render(double currentTime)
{
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
glBindVertexArray(vertexArrayID);
glDrawArrays(GL_LINE_STRIP, 0, 4);
//glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
顶点着色器
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
片元着色器
#version 330 core
// Ouput data
out vec3 color;
void main()
{
// Output color = red
color = vec3(1,0,0);
}
中点画线法:
void bges::CGfxRenderDDADrawLine::GetLineDatMLDAData(float x1,float y1,float x2,float y2, GLfloat lineVertexX[],GLfloat lineVertexY[])
{
float a = y1 - y2;
float b = x2 - x1;
float d = 2 * a + b;
float deta1 = 2 * a;
float deta2 = 2 * (a + b);
float x = x1,y = y1;
lineVertexX[ 0 ] = x;
lineVertexY[ 0 ] = y;
int i = 1;
for(;;)
{
if(x - x2 < 0.000001){
if(d - 0.0000001 < 0){
x = x + 0.1;
y = y + 0.1;
d = d + deta2;
}
else {
x = x + 0.1;
d = d + deta1;
}
lineVertexX[ i ] = x;
lineVertexY[ i ] = y;
printf("%f,%f\n",x,y);
i++;
}
else{
return;
}
}
}
中点画线法运行结果: