文章目录
- 示例1
- Vertex Shader
- Geometry Shader
- Fragment Shader
- 运行效果
- 几何着色器在管线的位置
- Geometry Shader 中主要部分
- 接受的输入图元类型
- 接受的输出图元类型
- 示例2
- Vertex Shader
- Geomestry Shader
- Fragment Shader
- 运行效果
- 示例3 - 显示顶点法线
- 实现思路
- 应用层代码
- Vertex Shader
- Geometry Shader
- Fragment Shader
- 运行效果
- Fur Shading
- References
LearnGL - 学习笔记目录
由于时间关系,没能详细的编写几何着色器相关的内容
几何着色器的学习也是早在差不多一个月前完整了,现在才有空补上
示例1加载网格部分,顶点数据有:位置、颜色信息
GLfloat temp_vertices[4 * 3] = {
-0.5f, +0.5f, 0.0f,
+0.5f, +0.5f, 0.0f,
+0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
GLfloat temp_colors[4 * 4] = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
};
GLuint temp_indices[4] = {
0, 1, 2, 3
};
mesh->pos_copy_from(temp_vertices, sizeof(temp_vertices) / sizeof(temp_vertices[0]));
mesh->color_copy_from(temp_colors, sizeof(temp_colors) / sizeof(temp_colors[0]));
mesh->indices_copy_from(temp_indices, sizeof(temp_indices) / sizeof(temp_indices[0]));
ReferMgr::setObj(mesh_ref_name.c_str(), mesh);
memcpy(mesh->name, mesh_ref_name.c_str(), mesh_ref_name.size() + 1);
mesh->primiveType = DrawState_PrimitiveType::POINTS;
加载着色器
// material - shader
std::string shader_ref_name = "TestingGeometryShader\\testing_geometry_shader";
shader = ReferMgr::getObj(shader_ref_name.c_str());
if (shader == NULL) {
shader = new ShaderProgram(shader_ref_name.c_str());
char vs_path[MAX_PATH], fs_path[MAX_PATH], gs_path[MAX_PATH];
g_GetShaderPathCallback(vs_path, "TestingGeometryShader\\testing_geometry_shader.vert");
g_GetShaderPathCallback(fs_path, "TestingGeometryShader\\testing_geometry_shader.frag");
g_GetShaderPathCallback(gs_path, "TestingGeometryShader\\testing_geometry_shader.geom");
if (!shader->initByPath(vs_path, fs_path, "", "", gs_path)) {
std::cout initByPath(vs_path, fs_path)) {
std::cout ref_name = ref_name;
setting->set_texture_obj(main_tex);
setting->name = "main_tex";
}
pass->enabledDepthWrite = false;
pass->enabledBlend = true;
pass->blendSrcFactor = DrawState_BlendFactorType::SRC_ALPHA;
pass->blendDstFactor = DrawState_BlendFactorType::ONE_MINUS_SRC_ALPHA;
pass->SrcRefractionK = 1.00f;
pass->DstRefractionK = 1.52f;
pass->UseTexAlpha = false;
pass->Alpha = 0.80f;
pass->ReflectionK = 1.0f;
pass->RefractionK = 0.5f;
pass->glossy = 100.0f;
}
// pass1
{
// material - shader1
std::string shader_ref_name = "TestingGeometryShaderDisplayNormals\\testing_geometry_shader_display_normals";
shader1 = ReferMgr::getObj(shader_ref_name.c_str());
if (shader1 == NULL) {
shader1 = new ShaderProgram(shader_ref_name.c_str());
char vs_path[MAX_PATH], fs_path[MAX_PATH], gs_path[MAX_PATH];
g_GetShaderPathCallback(vs_path, "TestingGeometryShaderDisplayNormals\\testing_geometry_shader_display_normals.vert");
g_GetShaderPathCallback(fs_path, "TestingGeometryShaderDisplayNormals\\testing_geometry_shader_display_normals.frag");
g_GetShaderPathCallback(gs_path, "TestingGeometryShaderDisplayNormals\\testing_geometry_shader_display_normals.geom");
if (!shader1->initByPath(vs_path, fs_path, "", "", gs_path)) {
std::cout getTrans()->local_position = vec3(1.2f, 0, i);
temp_go->getTrans()->local_position = vec3(0.0f, 0.0f, 0.0f);
temp_go->getTrans()->local_scale = vec3(1, 1, 1);
MyGeometryShader_Testing_Display_Normals* temp_comp = new MyGeometryShader_Testing_Display_Normals();
temp_comp->mesh_name = "Testing_Cube.m";
temp_go->addComp(temp_comp);
SceneMgr::inst()->getRoot()->add(temp_go);
}
{
// Sphere
GameObject* temp_go = new GameObject();
sprintf_s(name, "%s##%d", "GeemetryShaderTestingDisplayNormals", temp_go->id());
temp_go->set_name_copy_from(name);
//temp_go->getTrans()->local_position = vec3(1.2f, 0, i);
temp_go->getTrans()->local_position = vec3(1.0f, 0.0f, 0.0f);
temp_go->getTrans()->local_scale = vec3(1, 1, 1);
MyGeometryShader_Testing_Display_Normals* temp_comp = new MyGeometryShader_Testing_Display_Normals();
temp_comp->mesh_name = "Sphere_637003627289014299.m";
temp_go->addComp(temp_comp);
SceneMgr::inst()->getRoot()->add(temp_go);
}
{
// cube
GameObject* temp_go = new GameObject();
sprintf_s(name, "%s##%d", "GeemetryShaderTestingDisplayNormals", temp_go->id());
temp_go->set_name_copy_from(name);
//temp_go->getTrans()->local_position = vec3(1.2f, 0, i);
temp_go->getTrans()->local_position = vec3(2.0f, 0.0f, 0.0f);
temp_go->getTrans()->local_scale = vec3(1, 1, 1);
MyGeometryShader_Testing_Display_Normals* temp_comp = new MyGeometryShader_Testing_Display_Normals();
temp_comp->mesh_name = "BalloonStupidCat_637003750150312129.m";
temp_go->addComp(temp_comp);
SceneMgr::inst()->getRoot()->add(temp_go);
}
Vertex Shader
// jave.lin - testing_geometry_shader.vert
#version 450 compatibility
#extension GL_ARB_shading_language_include : require
#include "/Include/my_global.glsl"
in vec3 vPos;
in vec3 vNormal;
out VS_OUT {
vec3 normal;
};
void main() {
normal = ObjectToWorldNormal(vNormal); // 将模型空间的法线 转换到 世界坐标顶点法线
gl_Position = mMat * vec4(vPos, 1.0); // 世界坐标
}
Geometry Shader
// jave.lin - testing_geometry_shader.geos
#version 450 compatibility
#extension GL_ARB_shading_language_include : require
#include "/Include/my_global.glsl"
layout (triangles) in;
layout (line_strip, max_vertices = 2 * 3) out;
// 下面 in/out 是用 interface block 接口块来传输数据
in VS_OUT { // Vertex Shader 的输出
vec3 normal;
} gs_in[];
out GS_OUT { // Geometry Shader 的输出
vec4 col;
};
// 外部可控的 uniform
uniform float normal_line_len = 1; // 法线的长度
uniform int normal_type = 1; // 法线类型,0:三角面中心显示,1:面个顶点都显示
void center_point_normal_line() {
vec3 vec_1 = (gl_in[1].gl_Position - gl_in[0].gl_Position).xyz;
vec3 vec_2 = (gl_in[2].gl_Position - gl_in[0].gl_Position).xyz;
vec3 normal_vec = normalize(cross(vec_1, vec_2));
vec4 centerPos = (
gl_in[0].gl_Position +
gl_in[1].gl_Position +
gl_in[2].gl_Position) / 3.0;
gl_Position = pMat * vMat * centerPos;
EmitVertex();
gl_Position = pMat * vMat * vec4(centerPos.xyz + (normal_vec * normal_line_len), centerPos.w);
EmitVertex();
EndPrimitive();
}
void point_normal_line(int idx) {
gl_Position = pMat * vMat * gl_in[idx].gl_Position;
col = vec4(0, 0.5, 1, 1); // 法线头部颜色,浅蓝色
EmitVertex();
gl_Position = pMat * vMat * vec4(gl_in[idx].gl_Position.xyz + (gs_in[idx].normal * normal_line_len), 1);
col = vec4(1); // 法线尾部颜色,白色,便于查看法线是否正确
EmitVertex();
EndPrimitive();
}
void per_point_normal_line() {
point_normal_line(0);
point_normal_line(1);
point_normal_line(2);
}
void main() {
if (normal_type == 0) {
// 三角面中心
center_point_normal_line();
} else {
// 每个顶点
per_point_normal_line();
}
}
Fragment Shader
// jave.lin - testing_geometry_shader.frag
#version 450 compatibility
in GS_OUT {
vec4 col;
};
void main() {
gl_FragColor = col;
}
运行效果
在 OpenGL 第9版本的红宝书 中,还有使用 Geometry Shader 来使用 fur shading(毛发着色)
后面如果有空,我也会去尝试一下
References- OpenGL 编程指南 - 红宝书 - 第9版 - 第10章 - 393 页
- 几何着色器