[Manjaro] OpenGL 配合着色器实现光线跟踪之引入光线

本文介绍了如何在Manjaro Linux上使用GLFW和GLAD,结合GLSL着色器实现基于屏幕空间的光线跟踪。通过顶点和片段着色器,逐步实现从输出基础图像、向场景发射光线到绘制实心球以及基于表面法向量的简单着色,最终展示了一个颜色渐变的球体渲染效果。
摘要由CSDN通过智能技术生成

概述

本文介绍 GLFW + GLAD 在 RayTracing in one weekend 的实现。

实验环境:Manjaro Linux 22.0.0

整体思路:

使用基于屏幕空间的光线跟踪算法,每个像素点代表一个光线。使用 GLSL 着色器语言编写顶点着色器,获取顶点在屏幕空间的坐标,经过函数计算得到 RGB 值并传输到片段着色器中。

目录

概述

输出第一张图片

顶点着色器代码

片段着色器代码

向场景中发射光线

顶点着色器代码

片段着色器代码

画一个实心球

顶点着色器代码

简单的着色——基于表面法向量

顶点着色器


输出第一张图片

首先设置窗口尺寸

const unsigned int SCR_WIDTH = 400;
const unsigned int SCR_HEIGHT = 400;

设置参数

// 确定顶点大小
const int point_size = 1;

// 均匀等距采样
const int sample_x = SCR_WIDTH / point_size;
const int sample_y = SCR_HEIGHT / point_size;

// 确定顶点数组
const int num_of_points = sample_y * sample_x;
float vertices[num_of_points * 3];

因为 GPU 绘制顶点的时候是要通过输入的顶点数组来计算屏幕空间中的顶点,因此在 main 函数中通过 CPU 设置顶点三维坐标信息。

平常我们认为图像的空间坐标系中,坐标从 0 开始一直到边界,但是 OpenGL 中,屏幕空间是一个坐标取值为 [-1.0, 1.0] 的二维空间,因此需要进行坐标的转换。

int dy = SCR_HEIGHT / sample_y; // 顶点在虚拟屏幕空间的 y 轴步长
int dx = SCR_WIDTH / sample_x; // 顶点在虚拟屏幕空间 x 轴步长

int idx = 0;
printf("dy: %d dx: %d\n", dy, dx);

/* 遍历虚拟屏幕空间,将 [0, SCR_HEIGHT] 坐标变换到 [-1.0, 1.0] 的
 * 屏幕空间坐标并记录在 vertices 数组中 */
for (int y = 0; y < SCR_HEIGHT; y += dy) {
  for (int x = 0; x < SCR_WIDTH; x += dx) {
    float ny = (static_cast<float>(y) / SCR_HEIGHT - 0.5) * 2.0f;
    float nx = (static_cast<float>(x) / SCR_WIDTH - 0.5) * 2.0f;
    vertices[idx++] = nx;
    vertices[idx++] = ny;
    vertices[idx++] = 0.0f; // z 轴坐标,暂时设置为 0.0f
  }
}

在渲染主循环中,我们需要将顶点数据发送到 GPU,因此使用 glDrawArrays() 函数 ,参数设置为顶点个数。

glPointSize(point_size);
glDrawArrays(GL_POINTS, 0, num_of_points);

为了将顶点坐标映射成颜色值,还需要在着色器程序中进行一点小小的调整,将 [-1.0, 1.0] 的坐标轴变换到 [0.0, 1.0] 范围内。

vsOutColor.x = aPos.x / 2 + 0.5;
vsOutColor.y = aPos.y / 2 + 0.5;
vsOutColor.z = 0.25;

最终结果图如下

顶点着色器代码

// vertex shader
#version 460 core
layout (location = 0) in vec3 aPos;
out vec3 vsOutColor;
void main()
{
    vsOutColor.x = aPos.x / 2 + 0.5;
    vsOutColor.y = aPos.y / 2 + 0.5;
	vsOutColor.z = 0.25;
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
};

片段着色器代码

// fragment shader
#version 460 core
out vec4 FragColor;
in vec3 vsOutColor;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值