计图--变换

主要是觉得写顶点坐标的这个方法有点妙,记录一下,看能不能摸索出更好玩的用法来


画一个立方体

先创建8个顶点的数据,再使用EBO实现画12个三角形。实践中发现GL_QUADS已不可用。

创建8个定点的数据:

float vertex[24]  ={0};
int fac[] = {1,-1};
float l = 0.5;
for(int i = 0 ; i < 8; i++){
    vertex[i * 3] = l * fac[(i / 2)%2]; // +x: 0 1 4 5 ; -x:  2 3  6 7
    vertex[i * 3 + 1] = l * fac[i%2];  //+y:0 2 4 6     -y: 1 3 5 7 
    vertex[i * 3 + 2] = l * fac[i / 4];   // +z:0 1 2 3   -z: 4 5 6 7  
} 

创建索引数据,在注释中已表明属于哪一个面。实践过程中发现索引值的顺序会影响创建的图案:

unsigned int indices[] = {
    0,1,2,3,1,2, // front
    4,5,6,7,5,6, // back
    0,1,4,1,4,5, // right
    2,3,6,7,3,6, // left
    0,2,6,4,0,6,//top
    1,3,7, 1,5,7 // bottom
};

坐标序号对应的空间位置如图:

这里写图片描述

调用自定义函数newObjectEBO

int pointCount = 8;
int indexCount = 36;
newObjectEBO(&VAO1, &VBO1, &EBO1, indexCount, indices, pointCount, vertex);

为了区分不同的面,修改fragment shader如下:

#version 330 core  
out vec4 FragColor;
in vec3 oPos;
uniform vec4 fill;
void main()
{
    FragColor = vec4(oPos.x,oPos.y,fill.z, 0.5);
}

渲染时设置相应的VAO并调用glDrawElements,需要渲染的点数为36:

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);

效果:

这里写图片描述

自动的平移、旋转、变换

在GUI上设置是否自动变换:

ImGui::Checkbox("AutoPlay", &autoplay); ImGui::SameLine();
ImGui::Checkbox("autoscale", &autoscale); ImGui::SameLine();
ImGui::NewLine();
ImGui::Checkbox("autotrans", &autotrans); ImGui::SameLine();
ImGui::Checkbox("autorotate", &autorotate); ImGui::SameLine();
ImGui::NewLine();

根据用户选项对transform矩阵进行相应的赋值。

对于来回的平移和变换,用关于时间变量tsin实现。

对于绕y=z轴的旋转,将rotate函数的第三个变量(轴的normal vector)设置为(0,1,1)即可。

if (autoplay) {
    float t = (float)glfwGetTime() * 100;
    if (autorotate) transform = glm::rotate(transform, glm::radians(t), glm::vec3(0, 1, 1));
    if (autotrans)   transform = glm::translate(transform, glm::vec3(sin(t*0.01), 0, 0));
    float l = sin(t*0.05) + 0.2;
    if (autoscale) transform = glm::scale(transform, glm::vec3(l, l, l)); 
}

效果见GIF。

自定义变换

可输入的参数:

// transformation
ImGui::SliderFloat("translateX"W, &transx, -1.f, 1.0f);    
ImGui::SliderFloat("translateY", &transy, -1.f, 1.0f);    
ImGui::SliderFloat("translateZ", &transz, -1.f, 1.0f);   
ImGui::SliderFloat("rotateX", &rotatex, 0.01f, 360.0f);     
ImGui::SliderFloat("rotateY", &rotatey, 0.01f, 360.0f);     
ImGui::SliderFloat("rotateZ", &rotatez, 0.01f, 360.0f);     
ImGui::SliderFloat("scaleX", &scale.x, 0.01f, 3.0f);      
ImGui::SliderFloat("scaleY", &scale.y, 0.01f, 3.0f);    
ImGui::SliderFloat("scaleZ", &scale.z, 0.01f, 3.0f);     
ImGui::NewLine();

根据参数设置变换矩阵:

transform = glm::translate(transform, glm::vec3(transx, transy, transz));
transform = glm::rotate(transform, glm::radians(rotatex), glm::vec3(1, 0, 0));
transform = glm::rotate(transform, glm::radians(rotatey), glm::vec3(0, 1, 0));
transform = glm::rotate(transform, glm::radians(rotatez), glm::vec3(0, 0, 1));
transform = glm::scale(transform, glm::vec3(scale.x, scale.y, scale.z));

设置uniform值,输入到shader:

glUniformMatrix4fv(glGetUniformLocation(shaderprogram, "transform"), 1, GL_FALSE, glm::value_ptr(transform));

效果:
这里写图片描述

3D效果的实现

通过设置model, view, projection三个矩阵实现。

glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;

model = glm::rotate(model, 0.f, glm::vec3(1.0f, 1.0f, 0.0f)); 
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -4.0f));
projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);

参数说明:

model:从local spaceworld space,此处不做更改。

view:从world spaceview space, 此处将场景向z轴负方向移动,相当于把camera朝屏幕外移动了。

projection: perspective的第一个值是Field of view,这里设置为45°。宽高比设置为视口的宽/高。第3,4个值为near和far平面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值