国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

這篇具有很好參考價(jià)值的文章主要介紹了計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


術(shù)語Tessellation(鑲嵌)是指一大類設(shè)計(jì)活動(dòng),通常是指在平坦的表面上,用各種幾何形狀的瓷磚相鄰排列以形成圖案。它的目的可以是藝術(shù)性的或?qū)嵱眯缘?,很多例子可以追溯到幾千年前[TS16]。

在3D圖形學(xué)中,Tessellation指的是有點(diǎn)不同的東西(曲面細(xì)分),但顯然是由它的經(jīng)典對(duì)應(yīng)物(鑲嵌)啟發(fā)而成的。在這里,曲面細(xì)分指的是生成并且操控大量三角形以渲染復(fù)雜的形狀和表面,尤其是使用硬件進(jìn)行渲染。曲面細(xì)分是OpenGL核心近期才增加的新功能,在2010年的4.0版本中出現(xiàn)。

12.1 OpenGL中的曲面細(xì)分

OpenGL對(duì)硬件曲面細(xì)分的支持,通過3個(gè)管線階段提供:

(1)曲面細(xì)分控制著色器;
(2)曲面細(xì)分器;
(3)曲面細(xì)分評(píng)估著色器。

第(1)和第(3)階段是可編程的;而中間的第(2)階段不是。為了使用曲面細(xì)分,程序員通常會(huì)提供控制著色器和評(píng)估著色器。

曲面細(xì)分器(其全名是曲面細(xì)分圖元生成器,或TPG)是硬件支持的引擎,可以生成固定的三角形網(wǎng)格。控制著色器允許我們配置曲面細(xì)分器要構(gòu)建什么樣的三角形網(wǎng)格。然后,評(píng)估著色器允許我們以各種方式操控網(wǎng)格。然后,被操控過的三角形網(wǎng)格,會(huì)作為通過管線前進(jìn)的頂點(diǎn)的源數(shù)據(jù)。回想一下圖2.2,在管線上,曲面細(xì)分著色器位于頂點(diǎn)著色器和幾何著色器階段之間。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

讓我們從一個(gè)簡單的應(yīng)用程序開始,該應(yīng)用程序只使用曲面細(xì)分器創(chuàng)建頂點(diǎn)的三角形網(wǎng)格,然后在不進(jìn)行任何操作的情況下顯示它。 為此,我們需要以下模塊。

(1)C++/OpenGL應(yīng)用程序:
創(chuàng)建一個(gè)攝像機(jī)和相關(guān)的MVP矩陣,視圖(v)和投影§矩陣確定攝像機(jī)朝向,模型(m)矩陣可用于修改網(wǎng)格的位置和方向。
(2)頂點(diǎn)著色器:在這個(gè)例子中基本上什么都不做,頂點(diǎn)將在曲面細(xì)分器中生成。
(3)曲面細(xì)分控制著色器:指定曲面細(xì)分器要構(gòu)建的網(wǎng)格。
(4)曲面細(xì)分評(píng)估著色器:將MVP矩陣應(yīng)用于網(wǎng)格中的頂點(diǎn)。
(5)片段著色器:只需為每個(gè)像素輸出固定顏色。

程序12.1顯示了整個(gè)應(yīng)用程序的代碼。即使像這樣的簡單示例也相當(dāng)復(fù)雜,因此許多代碼元素都需要解釋。請(qǐng)注意,這是我們第一次使用除頂點(diǎn)和片段著色器之外的組件構(gòu)建GLSL渲染程序。因此,我們實(shí)現(xiàn)了createShaderProgram()的4參數(shù)重載版本。

程序12.1 基本曲面細(xì)分器網(wǎng)格

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分.
完整源代碼
vertShader.glsl

#version 430

uniform mat4 mvp_matrix;

void main(void)
{
}

fragShader.glsl

#version 430

out vec4 color;
uniform mat4 mvp_matrix;

void main(void)
{
	color = vec4(1.0, 1.0, 0.0, 1.0);
}

曲面細(xì)分控制著色器tessCShader.glsl

#version 430

uniform mat4 mvp_matrix;
layout (vertices = 1) out;

void main(void)
{	gl_TessLevelOuter[0] = 6;
	gl_TessLevelOuter[2] = 6;
	gl_TessLevelOuter[1] = 6;
	gl_TessLevelOuter[3] = 6;
	gl_TessLevelInner[0] = 12;
	gl_TessLevelInner[1] = 12;
}

曲面細(xì)分評(píng)估著色器tessEShader.glsl

#version 430

layout (quads, equal_spacing, ccw) in;

uniform mat4 mvp_matrix;

void main (void)
{
	float u = gl_TessCoord.x;
	float v = gl_TessCoord.y;
	gl_Position = mvp_matrix * vec4(u,0,v,1);
}

main.cpp

#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <SOIL2\soil2.h>
#include <string>
#include <iostream>
#include <fstream>
#include <glm\gtc\type_ptr.hpp> // glm::value_ptr
#include <glm\gtc\matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include "Utils.h"
using namespace std;

float toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }

#define numVAOs 1

//-------------------------------------------Utils util = Utils();
float cameraX, cameraY, cameraZ;
float terLocX, terLocY, terLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];

// variable allocation for display
GLuint mvpLoc;
int width, height;
float aspect;
glm::mat4 pMat, vMat, mMat, mvpMat;

float tessInner = 30.0f;
float tessOuter = 20.0f;

void init(GLFWwindow* window) {
	renderingProgram = Utils::createShaderProgram("vertShader.glsl", "tessCShader.glsl", "tessEShader.glsl", "fragShader.glsl");
	cameraX = 0.5f; cameraY = -0.5f; cameraZ = 2.0f;
	terLocX = 0.0f; terLocY = 0.0f; terLocZ = 0.0f;

	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
	
	glGenVertexArrays(numVAOs, vao);
	glBindVertexArray(vao[0]);
}

void display(GLFWwindow* window, double currentTime) {
	glClear(GL_DEPTH_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT);

	glUseProgram(renderingProgram);

	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));

	mMat = glm::translate(glm::mat4(1.0f), glm::vec3(terLocX, terLocY, terLocZ));
	mMat = glm::rotate(mMat, toRadians(35.0f), glm::vec3(1.0f, 0.0f, 0.0f));
	mvpMat = pMat * vMat * mMat;

	mvpLoc = glGetUniformLocation(renderingProgram, "mvp_matrix");

	glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvpMat));

	glFrontFace(GL_CCW);

	glPatchParameteri(GL_PATCH_VERTICES, 1);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  // FILL or LINE
	glDrawArrays(GL_PATCHES, 0, 1);
}

void window_size_callback(GLFWwindow* win, int newWidth, int newHeight) {
	aspect = (float)newWidth / (float)newHeight;
	glViewport(0, 0, newWidth, newHeight);
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
}

int main(void) {
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(800, 800, "Chapter12 - program1", NULL, NULL);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);

	glfwSetWindowSizeCallback(window, window_size_callback);

	init(window);

	while (!glfwWindowShouldClose(window)) {
		display(window, glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}

得到的輸出網(wǎng)格如圖12.1所示(見彩插)。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.1 Tessellator三角形網(wǎng)格輸出

曲面細(xì)分器生成由兩個(gè)參數(shù)定義的頂點(diǎn)網(wǎng)格:內(nèi)層級(jí)別和外層級(jí)別。在這種情況下,內(nèi)層級(jí)別為12,外層級(jí)別為6——網(wǎng)格的外邊緣被分為6段,而跨越內(nèi)部的線被分為12段。

程序12.1中的特別相關(guān)的新結(jié)構(gòu)被高亮顯示。讓我們首先討論第一部分——C++/ OpenGL代碼。

編譯這兩個(gè)新著色器,跟頂點(diǎn)和片段著色器完全相同。然后將它們附加到同一個(gè)渲染程序,并且鏈接調(diào)用保持不變。唯一的新項(xiàng)目是用于指定要實(shí)例化的著色器類型的常量——新常量如下:

GL_TESS_CONTROL_SHADER
GL_TESS_EVALUATION_SHADER

請(qǐng)注意display()函數(shù)中的新項(xiàng)目。glDrawArrays()調(diào)用現(xiàn)在指定 GL_PATCHES。當(dāng)使用曲面細(xì)分時(shí),從C++/OpenGL應(yīng)用程序發(fā)送到管線(即在VBO中)的頂點(diǎn)不會(huì)被渲染,但通常會(huì)被當(dāng)作控制點(diǎn),就像我們 在貝塞爾曲線中看到的那些一樣。一組控制點(diǎn)被稱作“補(bǔ)丁”,并且在使用曲面細(xì)分的代碼段中,GL_PATCHES是唯一允許的圖元類型。 “補(bǔ)丁”中頂點(diǎn)的數(shù)量在glPatchParameteri()的調(diào)用中指定。在這個(gè)特定示例中,沒有任何控制點(diǎn)被發(fā)送,但我們?nèi)匀恍枰付ㄖ辽僖粋€(gè)。類似地,在glDrawArrays()調(diào)用中,我們指示起始值為0,頂點(diǎn)數(shù)量為1,即使我們實(shí)際上沒有從C++程序發(fā)送任何頂點(diǎn)。

對(duì)glPolygonMode()的調(diào)用指定了如何光柵化網(wǎng)格。默認(rèn)值為 GL_FILL。而我們的代碼中顯示的是GL_LINE,如我們?cè)趫D12.1中看到的那樣,它只會(huì)導(dǎo)致連接線被光柵化(因此我們可以看到由曲面細(xì)分器生成的網(wǎng)格本身)。如果我們將該行代碼更改為GL_FILL(或?qū)⑵渥?釋掉,從而使用默認(rèn)行為GL_FILL),我們將得到如圖12.2所示的版本。

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.2 使用GL_FILL渲染的細(xì)分網(wǎng)格

現(xiàn)在讓我們來過一遍4個(gè)著色器。如前所述,頂點(diǎn)著色器幾乎沒什么可做的,因?yàn)镃++/OpenGL應(yīng)用程序沒有提供任何頂點(diǎn)。它包含的是一個(gè)統(tǒng)一變量聲明,以和其他著色器相匹配,以及一個(gè)空的main()。 在任何情況下,所有著色器程序都必須包含頂點(diǎn)著色器。

曲面細(xì)分控制著色器指定曲面細(xì)分器要生成的三角形網(wǎng)格的拓?fù)浣Y(jié)構(gòu)。通過將值分配給名為gl_TessLevelxxx的保留字,設(shè)置6個(gè)“級(jí)別”參數(shù)——兩個(gè)“內(nèi)部”和4個(gè)“外部”級(jí)別。我們這里細(xì)分了一個(gè) 由三角形組成的大矩形網(wǎng)格,稱為四邊形。[3]級(jí)別參數(shù)告訴曲面細(xì)分器在形成三角形時(shí)如何細(xì)分網(wǎng)格,它們的排列如圖12.3所示。

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.3 細(xì)分級(jí)別

請(qǐng)注意控制著色器中的代碼行:

layout (vertices=1) out;

這與之前的GL_PATCHES討論有關(guān),用來指定從頂點(diǎn)著色器傳遞給控制著色器(以及“輸出”給評(píng)估著色器)的每個(gè)“補(bǔ)丁”的頂點(diǎn)數(shù)。在我們現(xiàn)在這個(gè)程序中沒有任何頂點(diǎn),但我們?nèi)匀槐仨氈付ㄖ辽僖粋€(gè),因?yàn)樗矔?huì)影響控制著色器被執(zhí)行的次數(shù)。稍后這個(gè)值將反映控制點(diǎn)的數(shù)量,并且必須與C++/OpenGL應(yīng)用程序中glPatchParameteri()調(diào)用中的值匹配。

接下來讓我們看一下曲面細(xì)分評(píng)估著色器。它以一行代碼開頭,形如:

layout (quads, equal_spacing, ccw) in;

乍一看這好像與控件著色器中的“out”布局語句有關(guān),但實(shí)際上它們是無關(guān)的。相反,這行代碼是我們指示曲面細(xì)分器去生成排列在一個(gè)大矩形(“四邊形”)中頂點(diǎn)的位置。它還指定了細(xì)分線段(包括內(nèi)部和外部)具有相等的長度(稍后我們將看到長度不等的細(xì)分的應(yīng)用場景)?!癱cw”參數(shù)指定生成曲面細(xì)分網(wǎng)格頂點(diǎn)的纏繞順序(在當(dāng)前情況下,是逆時(shí)針)。

然后,由曲面細(xì)分器生成的頂點(diǎn)被發(fā)送到評(píng)估著色器。因此,評(píng)估著色器既可以從控制著色器(通常作為控制點(diǎn)),又可以從曲面細(xì)分器(曲面細(xì)分網(wǎng)格)接收頂點(diǎn)。在程序12.1中,僅從曲面細(xì)分器接收頂點(diǎn)。

評(píng)估著色器對(duì)曲面細(xì)分器生成的每個(gè)頂點(diǎn)執(zhí)行一次??梢允褂脙?nèi)置變量gl_TessCoord訪問頂點(diǎn)位置。曲面細(xì)分網(wǎng)格的朝向使得它位于X-Z平面中,因此gl_TessCoord的X和Y分量被應(yīng)用于網(wǎng)格的X和Z坐標(biāo)。網(wǎng)格坐標(biāo),以及 gl_TessCoord的值,范圍為0.0~1.0(這在計(jì)算紋理坐標(biāo)時(shí)會(huì)很方便)。然后,評(píng)估著色器使用MVP矩陣定向每個(gè)頂點(diǎn)(這在前面章節(jié)的示例中,是由頂點(diǎn)著色器完成的)。

最后,片段著色器只為每個(gè)像素輸出一個(gè)恒定的黃色。當(dāng)然,我們也可以使用它來為我們的場景應(yīng)用紋理或光照,就像我們?cè)谇懊娴恼鹿?jié)中看到的那樣。

12.2 貝塞爾曲面細(xì)分

現(xiàn)在讓我們擴(kuò)展我們的程序,使它將我們簡單的矩形網(wǎng)格轉(zhuǎn)換為貝塞爾曲面。細(xì)分網(wǎng)格應(yīng)該為我們提供了足夠的頂點(diǎn)來對(duì)曲面進(jìn)行采樣(如果我們想要更多的話,我們可以增加內(nèi)部/外部細(xì)分級(jí)別)。我們現(xiàn)在需要的是通過管線發(fā)送控制點(diǎn),然后使用這些控制點(diǎn)執(zhí)行計(jì)算以將細(xì)分網(wǎng)格轉(zhuǎn)換為我們所需的貝塞爾曲面。

假設(shè)我們希望建立一個(gè)立方體貝塞爾曲面,我們將需要16個(gè)控制點(diǎn)。我們可以通過VBO從C++端發(fā)送它們,或者我們可以在頂點(diǎn)著色器中硬編碼寫死它們。圖12.4概述了來自C++端的控制點(diǎn)的過程。

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.4 貝塞爾曲面的曲面細(xì)分概述

現(xiàn)在是更準(zhǔn)確地解釋曲面細(xì)分控制著色器(TCS)如何工作的好時(shí)機(jī)。與頂點(diǎn)著色器類似,TCS對(duì)每個(gè)傳入頂點(diǎn)執(zhí)行一次。另外,回想一下第2章,OpenGL提供了一個(gè)名為·gl_VertexID·的內(nèi)置變量,它保存一個(gè)計(jì)數(shù)器,指示頂點(diǎn)著色器當(dāng)前正在執(zhí)行哪次調(diào)用。曲面細(xì)分控制著色器中存在一個(gè)類似的內(nèi)置變量gl_InvocationID。

曲面細(xì)分的一個(gè)強(qiáng)大功能是TCS(以及TES)著色器可以同時(shí)訪問數(shù)組中的所有控制點(diǎn)頂點(diǎn)。首先,當(dāng)每個(gè)調(diào)用都可以訪問所有頂點(diǎn)時(shí),TCS對(duì)每個(gè)頂點(diǎn)執(zhí)行一次可能會(huì)讓人感到困惑。在每個(gè)TCS調(diào)用中,冗余地在賦值語句中指定曲面細(xì)分級(jí)別也是違反直覺的。盡管所 有這些看起來都很奇怪,但這樣做是因?yàn)榍婕?xì)分的架構(gòu)設(shè)計(jì)使得TCS 調(diào)用可以并行運(yùn)行。

OpenGL提供了幾個(gè)用于TCS和TES著色器的內(nèi)置變量。我們已經(jīng)提到過的是gl_InvocationID,當(dāng)然還有gl_TessLevelInnergl_TessLevelOuter。以下是一些最有用的內(nèi)置變量的更多細(xì)節(jié)和描述。

  • 曲面細(xì)分控制著色器(TCS)內(nèi)置變量。
    gl_in[ ]——包含每個(gè)傳入的控制點(diǎn)頂點(diǎn)的數(shù)組——每個(gè)傳入頂點(diǎn)是一個(gè)數(shù)組元素??梢允褂谩?”表示法將特定頂點(diǎn)屬性作為字段進(jìn)行訪問。一個(gè)內(nèi)置屬性是gl_Position——因此,輸入頂點(diǎn)“i”的位置可以通過gl_in[i].gl_Position訪問。
    gl_out[ ]——用于將輸出控制點(diǎn)的頂點(diǎn)發(fā)送到TES的一個(gè)數(shù)組——每個(gè)輸出頂點(diǎn)是一個(gè)數(shù)組元素??梢允褂谩?”表示法將特定 頂點(diǎn)屬性作為字段進(jìn)行訪問。一個(gè)內(nèi)置屬性是gl_Position——因此,輸出頂點(diǎn)“i”的位置可以通過gl_out[i].gl_Position訪問。gl_InvocationID——整型ID計(jì)數(shù)器,指示TCS當(dāng)前正在執(zhí)行哪個(gè)調(diào)用。一個(gè)常見的用途是用于傳遞頂點(diǎn)屬性;例如,將當(dāng)前調(diào)用 的頂點(diǎn)位置從TCS傳遞到TES可以用如下方式完成: gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position。

  • 曲面細(xì)分評(píng)估著色器(TES)內(nèi)置變量。
    gl_in[ ]——包含每個(gè)傳入的控制點(diǎn)頂點(diǎn)的數(shù)組——每個(gè)傳入頂點(diǎn)是一個(gè)數(shù)組元素??梢允褂谩?”表示法將特定頂點(diǎn)屬性作為字段進(jìn)行訪問。一個(gè)內(nèi)置屬性是gl_Position——因此,輸入頂點(diǎn) “i”的位置可以通過gl_in[i].gl_Position訪問。
    gl_Position——曲面細(xì)分網(wǎng)格頂點(diǎn)的輸出位置,可能在TES中被修改。重要的是要注意gl_Positiongl_in[xxx].gl_Position是不同的——gl_Position是起源于曲面細(xì)分器的輸出頂點(diǎn)的位置,而gl_in[xxx].gl_Position是一個(gè)從TCS進(jìn)入TES的控制點(diǎn)頂點(diǎn)位置。

值得注意的是,TCS中的輸入和輸出控制點(diǎn)頂點(diǎn)屬性是數(shù)組。不同的是,TES中的輸入控制點(diǎn)頂點(diǎn)和頂點(diǎn)屬性是數(shù)組,但輸出頂點(diǎn)是標(biāo)量。此外,很容易混淆哪些頂點(diǎn)來自于控制點(diǎn),哪些頂點(diǎn)是細(xì)分建立的,然后移動(dòng)以形成結(jié)果曲面。總而言之,TCS的所有頂點(diǎn)輸入和輸出都是控制點(diǎn),而在TES中,gl_in[ ]保存輸入控制點(diǎn),gl_TessCoord保存輸入的細(xì)分網(wǎng)格點(diǎn),gl_Position保存用于渲染的輸出表面頂點(diǎn)。

我們的曲面細(xì)分控制著色器現(xiàn)在有兩個(gè)任務(wù):指定曲面細(xì)分級(jí)別并將控制點(diǎn)從頂點(diǎn)著色器傳遞到評(píng)估著色器。然后,評(píng)估著色器可以根據(jù)貝塞爾控制點(diǎn)修改網(wǎng)格點(diǎn)(gl_TessCoords)的位置。

程序12.2顯示了所有4個(gè)著色器——頂點(diǎn)、TCS、TES和片段——用于指定控制點(diǎn)補(bǔ)丁,生成平坦的曲面細(xì)分頂點(diǎn)網(wǎng)格,在控制點(diǎn)指定的曲面上重新定位這些頂點(diǎn),并使用紋理圖像繪制生成的曲面。它還顯示了C++/OpenGL應(yīng)用程序的相關(guān)部分,特別是在display()函數(shù)中。在 此示例中,控制點(diǎn)源自頂點(diǎn)著色器(它們?cè)谀抢镉簿幋a寫死),而不是從C++/OpenGL應(yīng)用程序進(jìn)入OpenGL管線。代碼后面會(huì)講述其他詳細(xì)信息。

程序12.2 貝塞爾曲面的曲面細(xì)分

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

頂點(diǎn)著色器現(xiàn)在指定代表特定貝塞爾曲面的16個(gè)控制點(diǎn)(“補(bǔ)丁”頂點(diǎn))。在這個(gè)例子中,它們都被歸一化到范圍[?1…+1]。頂點(diǎn)著色器還使用控制點(diǎn)來確定適合細(xì)分網(wǎng)格的紋理坐標(biāo),其值在[0…1]范圍內(nèi)。很重要的是,要重申頂點(diǎn)著色器輸出的頂點(diǎn)不是將要用來光柵化的頂點(diǎn),而是貝塞爾控制點(diǎn)。使用曲面細(xì)分時(shí),補(bǔ)丁頂點(diǎn)永遠(yuǎn)不會(huì)被光柵化——只有曲面細(xì)分頂點(diǎn)會(huì)被光柵化。

控制著色器仍然會(huì)指定內(nèi)部和外部曲面細(xì)分級(jí)別。它現(xiàn)在還負(fù)責(zé)將控制點(diǎn)和紋理坐標(biāo)發(fā)送到評(píng)估著色器。請(qǐng)注意,曲面細(xì)分級(jí)別只需要指定一次,因此該步驟僅在第0次調(diào)用期間完成(回想一下TCS每個(gè)頂點(diǎn)運(yùn)行一次,因此在此示例中有16次調(diào)用)。為方便起見,我們?yōu)槊總€(gè)細(xì)分級(jí)別指定了32個(gè)細(xì)分。

接下來,評(píng)估著色器執(zhí)行所有貝塞爾曲面計(jì)算。main()開頭的大塊賦值語句從每個(gè)傳入gl_ingl_Position中提取控制點(diǎn)(請(qǐng)注意,這些控制點(diǎn)對(duì)應(yīng)于控制著色器的gl_out變量)。然后使用來自曲面細(xì)分器的網(wǎng)格點(diǎn)計(jì)算混合函數(shù)的權(quán)重,從而生成一個(gè)新的outputPosition,然后應(yīng)用模型-視圖-投影矩陣,為每個(gè)網(wǎng)格點(diǎn)生成輸出gl_Position并形成貝塞爾曲面。

另外,還需要?jiǎng)?chuàng)建紋理坐標(biāo)。頂點(diǎn)著色器僅為每個(gè)控制點(diǎn)位置提供一個(gè)紋理坐標(biāo)。但我們并不是要渲染控制點(diǎn),我們最終需要更多的曲面細(xì)分網(wǎng)格點(diǎn)的紋理坐標(biāo)。有很多方法可以做到這一點(diǎn),在這里我們利用GLSL方便的混合功能對(duì)它們進(jìn)行線性插值。mix()函數(shù)需要3個(gè)參數(shù):
(a)起始點(diǎn);
(b)結(jié)束點(diǎn);
(c)內(nèi)插值,范圍為0~1。
它返 回與內(nèi)插值對(duì)應(yīng)的起點(diǎn)和終點(diǎn)之間的值。由于細(xì)分網(wǎng)格坐標(biāo)的范圍也是0~1,所以它們可以直接用于此目的。

這次在片段著色器中,不再是輸出單一顏色,而是應(yīng)用標(biāo)準(zhǔn)紋理。屬性texCoord_TESout中的紋理坐標(biāo)是在評(píng)估著色器中生成的紋理坐標(biāo)。對(duì)C++程序的更改同樣很簡單——請(qǐng)注意,現(xiàn)在指定的補(bǔ)丁大小為16。結(jié)果輸出如圖12.5所示(應(yīng)用了[LU16]的平鋪紋理)。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.5 曲面細(xì)分過的貝塞爾曲面

12.3 地形、高度圖的細(xì)分

回想一下,在頂點(diǎn)著色器中執(zhí)行高度貼圖可能會(huì)遇到頂點(diǎn)數(shù)量不足以用來渲染所需的細(xì)節(jié)的情況?,F(xiàn)在我們有了生成大量頂點(diǎn)的方 法,讓我們回到Hastings-Trew的月球表面紋理貼圖[HT16]并將其用作高度貼圖,提升曲面細(xì)分頂點(diǎn)來生成月球表面細(xì)節(jié)。正如我們將看到的,這具有一些優(yōu)點(diǎn),可以讓頂點(diǎn)的幾何形狀更好地匹配月亮圖像, 并且提升輪廓(邊緣)細(xì)節(jié)。

我們的策略是修改程序12.1,在X-Z平面中放置細(xì)分網(wǎng)格,并使用高度貼圖來設(shè)置每個(gè)細(xì)分網(wǎng)格點(diǎn)的Y坐標(biāo)。要做到這一點(diǎn),我們不需要補(bǔ)丁,因?yàn)榭梢杂簿幋a細(xì)分網(wǎng)格的位置,因此我們將在glDrawArrays()glPatchParameteri()中為每個(gè)補(bǔ)丁指定所需的最少的1個(gè)頂點(diǎn),如程序12.1中所做的那樣。Hastings-Trew的月亮紋理圖像既用于顏色,也用作高度圖。

我們通過將曲面細(xì)分網(wǎng)格的gl_TessCoord值映射到頂點(diǎn)和紋理的適當(dāng)范圍,在評(píng)估著色器中生成頂點(diǎn)和紋理坐標(biāo)。[4]評(píng)估著色器也通過添加月亮紋理的一小部分顏色分量到輸出頂點(diǎn)的Y分量,來實(shí)現(xiàn)高度貼圖。著色器的更改顯示在程序12.3中。

程序12.3 簡單的地形曲面細(xì)分

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

這里的片段著色器類似于程序12.2的,只是根據(jù)紋理圖像輸出顏色。C++/OpenGL應(yīng)用程序基本上沒有變化——它加載紋理(用作紋理 和高度圖)并為其啟用采樣器。圖12.6顯示了紋理圖像(左側(cè))和第一次嘗試的最終輸出,遺憾的是,它還沒有實(shí)現(xiàn)正確的高度貼圖。

第一次結(jié)果存在嚴(yán)重缺陷。雖然我們現(xiàn)在可以看到遠(yuǎn)處地平線上的輪廓細(xì)節(jié),但是那里的凸起與紋理貼圖中的實(shí)際細(xì)節(jié)不對(duì)應(yīng)。回想一下,在高度圖中,白色應(yīng)該表示“高”,而黑色應(yīng)該表示“低”。 特別是圖像右上方的區(qū)域顯示的大山丘與其中的淺色和深色無關(guān)。

導(dǎo)致此問題的原因是細(xì)分網(wǎng)格的分辨率。曲面細(xì)分器可以生成的最大頂點(diǎn)數(shù)取決于硬件。要符合OpenGL標(biāo)準(zhǔn),唯一的要求是每個(gè)曲面細(xì)分級(jí)別的最大值至少為64。我們的程序指定了一個(gè)內(nèi)部和外部曲面細(xì)分級(jí)別均為32的單一細(xì)分網(wǎng)格,因此我們生成了大約32×32或者說剛剛超過1 000個(gè)頂點(diǎn),這不足以準(zhǔn)確反映圖像中的細(xì)節(jié)。這在圖12.6右上方(圖中放大)尤其明顯——邊緣細(xì)節(jié)僅在沿地平線的32個(gè)點(diǎn)處采樣,這會(huì)產(chǎn)生巨大而看起來很隨機(jī)的山丘。即使我們將曲面細(xì)分值增加到64,總共64×64或剛剛超過4 000個(gè)頂點(diǎn)仍然不足以滿足使用月球圖像進(jìn)行高度貼圖的需要。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.6 細(xì)分地形——首次嘗試失敗,頂點(diǎn)數(shù)量不足

增加頂點(diǎn)數(shù)量的一個(gè)好方法是使用我們?cè)诘?章中看到的實(shí)例化。 我們的策略是讓曲面細(xì)分器生成網(wǎng)格,并使用實(shí)例化重復(fù)數(shù)次。在頂點(diǎn)著色器中,我們構(gòu)建了一個(gè)由4個(gè)頂點(diǎn)定義的補(bǔ)丁,每個(gè)頂點(diǎn)用于細(xì)分網(wǎng)格的每個(gè)角。在我們的C++/OpenGL應(yīng)用程序中,我們將glDrawArrays()調(diào)用更改為glDrawArraysInstanced()。如此,我們指定一個(gè)64×64個(gè)補(bǔ)丁的網(wǎng)格,每個(gè)補(bǔ)丁包含一個(gè)細(xì)分級(jí)別為32的網(wǎng)格。這將帶給我們總共64×64×32×32個(gè),或者說超過400萬個(gè)頂點(diǎn)。

頂點(diǎn)著色器首先指定4個(gè)紋理坐標(biāo)(0,0)、(0,1)、(1,0)和(1,1)。 使用實(shí)例化時(shí),請(qǐng)回想一下,頂點(diǎn)著色器可以訪問整數(shù)變量 gl_InstanceID,它包含一個(gè)對(duì)應(yīng)于當(dāng)前正在處理的 glDrawArraysInstanced()調(diào)用的計(jì)數(shù)器。我們使用此ID值來分配大網(wǎng)格中各個(gè)補(bǔ)丁的位置。補(bǔ)丁位于行和列中,第一個(gè)補(bǔ)丁位于(0,0),第 二個(gè)位于(1,0),下一個(gè)位于(2,0),依此類推,第一列中的最后一個(gè) 補(bǔ)丁在(63,0)。下一列的補(bǔ)丁位于(0,1)、(1,1),依此類推,直至 (63,1)。最后一列的補(bǔ)丁位于(0,63)、(1,63),依此類推,最后是(63,63)。給定補(bǔ)丁的X坐標(biāo)是實(shí)例ID整除64,Y坐標(biāo)是實(shí)例ID除以64(整數(shù)除法)。然后著色器將坐標(biāo)向下縮放到范圍[0…1]。

控制著色器沒有更改,除了它將頂點(diǎn)和紋理坐標(biāo)傳遞下去。

接下來,評(píng)估著色器獲取傳入的細(xì)分網(wǎng)格頂點(diǎn)(由gl_TessCoord指定)并將它們移動(dòng)到傳入補(bǔ)丁指定的坐標(biāo)范圍內(nèi)。它對(duì)紋理坐標(biāo)也進(jìn)行一樣的處理,并且也會(huì)以與程序12.3中相同的方式應(yīng)用高度貼圖。片段著色器沒有修改。

每個(gè)組件的更改顯示在程序12.4中。結(jié)果如圖12.7所示。請(qǐng)注意,高點(diǎn)和低點(diǎn)現(xiàn)在更接近于圖像的亮部和暗部。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.7 細(xì)分地形——第二次嘗試,使用實(shí)例化

程序12.4 實(shí)例化細(xì)分地形

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分
現(xiàn)在我們已經(jīng)實(shí)現(xiàn)了高度貼圖,我們可以著手改進(jìn)它并整合光照。一個(gè)挑戰(zhàn)是我們的頂點(diǎn)還沒有與它們相關(guān)的法向量。另一個(gè)挑戰(zhàn)是簡單地使用紋理圖像作為高度圖產(chǎn)生了過度“鋸齒狀”的結(jié)果——在這種情況下是因?yàn)椴⒎羌y理圖像中的所有灰度變化都是由高度引起的。對(duì)于這個(gè)特定的紋理貼圖,Hastings-Trew已經(jīng)生成了一個(gè)改進(jìn)的高度貼圖,我們可以使用[HT16]。如圖12.8左圖所示。我們可以通過生成相鄰頂點(diǎn)(或高度圖中的相鄰紋素)的高度,構(gòu)建連接它們的向量以及使用叉積來計(jì)算法向量,以動(dòng)態(tài)計(jì)算和創(chuàng)建法向量。這需要一些細(xì)微的調(diào)整,具體取決于場景的精度(和/或高度圖圖像)。在這里,我們使用GIMP“normalmap”插件[GP16]來根據(jù)Hastings-Trew的高度圖生成法線貼圖,如圖12.8右圖所示。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.8 月球表面:高度圖[HT16](左)和法線貼圖(右)

我們對(duì)代碼進(jìn)行的大部分更改現(xiàn)在只是為了實(shí)現(xiàn)Phong著色的標(biāo)準(zhǔn)方法。

  • C++/OpenGL應(yīng)用程序。

我們加載并激活一個(gè)額外的紋理來保存法線貼圖,還添加了代碼來指定光照和材質(zhì),就像我們?cè)谝郧暗膽?yīng)用程序中所做的那樣。

  • 頂點(diǎn)著色器。

唯一的增補(bǔ)是光照統(tǒng)一變量的聲明和法線貼圖的采樣器。通常在頂點(diǎn)著色器中完成的光照代碼被移動(dòng)到曲面細(xì)分評(píng)估著色器,因?yàn)橹钡角婕?xì)分階段才生成頂點(diǎn)。

  • 曲面細(xì)分控制著色器。

唯一的增補(bǔ)是光照統(tǒng)一變量的聲明和法線貼圖的采樣器。

  • 曲面細(xì)分評(píng)估著色器。

Phong光照的準(zhǔn)備代碼現(xiàn)在放在評(píng)估著色器中:

varyingVertPos = (mv_matrix * position).xyz;
varyingLightDir = light.position - varyingVertPos;
  • 片段著色器。

這里完成了用于計(jì)算Phong(或Blinn-Phong)照明的典型代碼段,以及從法線貼圖中提取法向量的代碼。然后將光照結(jié)果與紋理圖像用加權(quán)求和的方式結(jié)合起來。

帶有高度和法線貼圖以及Phong照明的最終結(jié)果如圖12.9所示。地形現(xiàn)在會(huì)響應(yīng)光照。在此示例中,位置光已放置在左側(cè)圖像中心的左側(cè),右側(cè)圖像中心的右側(cè)。
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.9 具有法線貼圖和光照的曲面細(xì)分地形(光源分別位于左側(cè)和右側(cè))

盡管從靜止圖像很難判斷出對(duì)光的移動(dòng)的響應(yīng),但是讀者應(yīng)該能夠辨別出漫射光的變化,并且山峰的鏡面高光在兩個(gè)圖像中是非常不同的。當(dāng)攝像機(jī)或光源移動(dòng)時(shí),這當(dāng)然會(huì)更明顯。結(jié)果仍然不完美,因?yàn)闊o論什么樣的光照,輸出中包含的原始紋理都包括了將出現(xiàn)在渲染結(jié)果上的陰影。

12.4 控制細(xì)節(jié)級(jí)別(LOD)

在程序12.4中,使用實(shí)例化來實(shí)時(shí)生成數(shù)百萬個(gè)頂點(diǎn),即使是裝備精良的現(xiàn)代計(jì)算機(jī)也可能會(huì)感受到負(fù)擔(dān)。幸運(yùn)的是,將地形劃分為單獨(dú)的補(bǔ)丁的策略,正如我們?yōu)樵黾由傻木W(wǎng)格頂點(diǎn)的數(shù)量所做的那樣,也為我們提供了一種減少負(fù)擔(dān)的好機(jī)制。

在生成的數(shù)百萬個(gè)頂點(diǎn)中,許多頂點(diǎn)不是必需的??拷鼣z像機(jī)的補(bǔ)丁中的頂點(diǎn)非常重要,因?yàn)槲覀兿M軌蜃R(shí)別附近物體的細(xì)節(jié)。但是,補(bǔ)丁越遠(yuǎn)離攝像機(jī),甚至光柵化過程中有足夠的像素來體現(xiàn)我們生成的頂點(diǎn)數(shù)量的可能性就越?。?/p>

根據(jù)距攝像機(jī)的距離更改補(bǔ)丁中的頂點(diǎn)數(shù)量是一種稱為細(xì)節(jié)級(jí)別或LOD的技術(shù)。Sellers等人描述了一種通過修改控制著色器來控制實(shí)例化曲面細(xì)分中的LOD的方法[SW15]。程序12.5顯示了Sellers等人的方法的簡化版本。策略是使用補(bǔ)丁的感知大小來確定其曲面細(xì)分級(jí)別的值。由于補(bǔ)丁的細(xì)分網(wǎng)格最終將放置在由進(jìn)入控制著色器的4個(gè)控制點(diǎn)定義的方格內(nèi),我們可以使用控制點(diǎn)相對(duì)于攝像機(jī)的位置來確定應(yīng)該為補(bǔ)丁生成多少個(gè)頂點(diǎn)。其步驟如下。
(1)通過將MVP矩陣應(yīng)用于4個(gè)控制點(diǎn),計(jì)算它們的屏幕位置。
(2)計(jì)算由控制點(diǎn)(在屏幕上的空間中)定義的正方形邊長(即寬度和高度)。請(qǐng)注意,即使4個(gè)控制點(diǎn)形成正方形,這些邊長也可能不同,因?yàn)閼?yīng)用了透視矩陣。
(3)根據(jù)曲面細(xì)分級(jí)別所需的精度(基于高度圖中的細(xì)節(jié)數(shù)量),將長度的值按可調(diào)整常數(shù)進(jìn)行縮放。
(4)將縮放長度值加1,以避免將曲面細(xì)分級(jí)別指定為0(這將導(dǎo)致不生成頂點(diǎn))。
(5)將曲面細(xì)分級(jí)別設(shè)置為相應(yīng)的計(jì)算寬度和高度值。
回想一下,在我們的實(shí)例中,我們不是只創(chuàng)建一個(gè)網(wǎng)格,而是創(chuàng)建64×64個(gè)網(wǎng)格。因此,對(duì)每個(gè)補(bǔ)丁執(zhí)行以上列表中的5個(gè)步驟,細(xì)節(jié)級(jí)別因補(bǔ)丁而異。所有更改都在控制著色器中,并顯示在程序12.5中,生成的輸出如圖12.10所示。請(qǐng)注意,變量gl_InvocationID指的是正在處理補(bǔ)丁中的哪個(gè)頂點(diǎn)(而不是正在處理哪個(gè)補(bǔ)?。R虼?,告訴曲面細(xì)分器在每個(gè)補(bǔ)丁中生成多少個(gè)頂點(diǎn)的LOD計(jì)算發(fā)生在每個(gè)補(bǔ)丁的第0個(gè)頂點(diǎn)期間

程序12.5 曲面細(xì)分細(xì)節(jié)級(jí)別(LOD)
計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

將這些控制著色器的更改應(yīng)用于圖12.7中我們場景的實(shí)例化(但不帶光照)版本,并將高度圖替換為Hastings-Trew的更精細(xì)調(diào)整的版本(如圖12.8所示),將會(huì)生成改善的場景,帶有更逼真的地平線細(xì)節(jié)(如圖12.10所示)。

在此示例中,更改評(píng)估著色器中的布局說明符也很有用:

layout (quads, equal_spacing) in;

更改為:

layout (quads, fractional_even_spacing) in;

計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分

圖12.10 具有控制細(xì)節(jié)級(jí)別(LOD)的曲面細(xì)分月亮

在靜止圖像中難以說明這種修改的原因。在動(dòng)畫場景中,當(dāng)曲面細(xì)分對(duì)象在3D空間中移動(dòng)時(shí),如果使用LOD,有時(shí)可以在對(duì)象表面上看到曲面細(xì)分級(jí)別的變化,看起來像一種叫作“彈出”的擺動(dòng)偽影。從等間距變?yōu)榉謹(jǐn)?shù)間距,通過使相鄰補(bǔ)丁實(shí)例的網(wǎng)格幾何體更相似,達(dá)成了即使它們的細(xì)節(jié)級(jí)別不同,也可以減少此影響的目的。(參見習(xí) 題12.2和12.3。)

使用LOD可以顯著降低系統(tǒng)負(fù)載。例如,在動(dòng)畫時(shí),如果不控制 LOD,場景可能會(huì)出現(xiàn)不穩(wěn)定或滯后的情況。

將這種簡單的LOD技術(shù)應(yīng)用于包含Phong著色的版本(程序12.4)有點(diǎn)棘手。這是因?yàn)橄噜徰a(bǔ)丁實(shí)例之間的LOD變化反過來會(huì)導(dǎo)致相關(guān)法向量的突然變化,從而導(dǎo)致光照中的彈出偽影!與以往一樣,在構(gòu)建復(fù)雜的3D場景時(shí)需要權(quán)衡和妥協(xié)。

補(bǔ)充說明

將曲面細(xì)分與LOD組合在實(shí)時(shí)虛擬現(xiàn)實(shí)應(yīng)用中特別有用,例如在計(jì)算機(jī)游戲中,其需要復(fù)雜的現(xiàn)實(shí)主義細(xì)節(jié)和頻繁的物體移動(dòng)和/或攝像機(jī)位置的變化。在本章中,我們已經(jīng)說明了曲面細(xì)分和LOD用于實(shí)時(shí)地 形生成的應(yīng)用場景,盡管它也可以應(yīng)用于其他領(lǐng)域,例如3D模型的位移貼圖(曲面細(xì)分頂點(diǎn)被添加到模型的表面,然后被移動(dòng)以便添加細(xì)節(jié))在計(jì)算機(jī)輔助設(shè)計(jì)應(yīng)用程序中也很有用。

Sellers等人通過消除攝像機(jī)后方的補(bǔ)丁中的頂點(diǎn)(他們通過將內(nèi) 部和外部級(jí)別設(shè)置為零來實(shí)現(xiàn)這一點(diǎn))[SW15],進(jìn)一步擴(kuò)展了LOD技術(shù)(在程序12.5中顯示)。這是一個(gè)剔除技術(shù)的示例,是一項(xiàng)非常有用 的技術(shù),因?yàn)閷?shí)例化細(xì)分的負(fù)載仍然可以在系統(tǒng)上正常運(yùn)行。

程序12.1中描述的createShaderProgram()的4參數(shù)版本被添加到Utils.cpp文件中。稍后,我們將添加其他版本以適應(yīng)幾何著色器階段。文章來源地址http://www.zghlxwxcb.cn/news/detail-481998.html

到了這里,關(guān)于計(jì)算機(jī)圖形學(xué)與opengl C++版 學(xué)習(xí)筆記 第12章 曲面細(xì)分的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • golang,OpenGL,計(jì)算機(jī)圖形學(xué)(三)

    golang,OpenGL,計(jì)算機(jī)圖形學(xué)(三)

    代碼倉庫 https://github.com/phprao/go-graphic 顏色 光源照射到物體上,一部分顏色被吸收,另一部分無法吸收的被反射到人眼,于是呈現(xiàn)出了顏色。 當(dāng)我們把光源的顏色與物體的顏色值 相乘 (而不是點(diǎn)乘),所得到的就是這個(gè)物體所反射的顏色。由此,我們可以定義物體的顏色為

    2024年02月12日
    瀏覽(53)
  • 【計(jì)算機(jī)圖形學(xué)】OpenGL遞歸實(shí)現(xiàn)光線追蹤

    【計(jì)算機(jī)圖形學(xué)】OpenGL遞歸實(shí)現(xiàn)光線追蹤

    計(jì)算機(jī)圖形學(xué)課程設(shè)計(jì):基于面向?qū)ο蟮墓饩€跟蹤算法設(shè)計(jì)與實(shí)現(xiàn) 目錄 一、前言 二、項(xiàng)目實(shí)現(xiàn)與說明 1. 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì) 1.1 光線 Ray 1.2 材質(zhì) Material 1.3 光照 Light 1.4 相機(jī) Camera 1.5 球體Sphere 1.6 場景Scene 2. 算法實(shí)現(xiàn) 2.1 光線追蹤算法原理與步驟 2.2 計(jì)算觀察光線 2.3 光線與物體(球

    2024年02月08日
    瀏覽(20)
  • 計(jì)算機(jī)圖形學(xué)實(shí)驗(yàn)四 OpenGL的鼠標(biāo)交互繪制

    一、實(shí)驗(yàn)?zāi)康?1.掌握OpenGL的鼠標(biāo)按鈕響應(yīng)函數(shù)。 2.掌握OpenGL的鼠標(biāo)移動(dòng)響應(yīng)函數(shù)。 3.進(jìn)一步鞏固OpenGL的基本圖元繪制基礎(chǔ)。 二、實(shí)驗(yàn)內(nèi)容 1.鼠標(biāo)畫草圖——實(shí)現(xiàn)鼠標(biāo)點(diǎn)到哪,線就畫到哪。 思路: 1)在主程序注冊(cè)鼠標(biāo)響應(yīng)和鼠標(biāo)移動(dòng)子函數(shù): glutMouseFunc(mymouse); glutMotionFunc(mym

    2023年04月20日
    瀏覽(104)
  • GAMES101 計(jì)算機(jī)圖形學(xué) | 學(xué)習(xí)筆記 (上)

    GAMES101 計(jì)算機(jī)圖形學(xué) | 學(xué)習(xí)筆記 (上)

    1. C++中安裝opencv庫 2. C++中安裝eigen庫 3. C++中安裝openGL庫 步驟(1)glut下載 4. C++安裝openGL庫 步驟(2)VS中安裝兩個(gè)NuGet程序包 5. C++安裝glew和glfw工具庫 要注意的是 glew.h必須包含再glut.h之前 。 如下: 計(jì)算機(jī)圖形學(xué)是利用計(jì)算機(jī)技術(shù)進(jìn)行圖像和視覺內(nèi)容的創(chuàng)建、處理和顯示的領(lǐng)

    2024年02月03日
    瀏覽(22)
  • 【計(jì)算機(jī)圖形學(xué) 】掃描線多邊形填充算法 | OpenGL+鼠標(biāo)交互

    【計(jì)算機(jī)圖形學(xué) 】掃描線多邊形填充算法 | OpenGL+鼠標(biāo)交互

    傳送門 實(shí)現(xiàn)多邊形掃描線填充算法,并和鼠標(biāo)進(jìn)行交互。 具體原理略過,會(huì)貼上完整代碼,可直接運(yùn)行。 環(huán)境: vs2019,OpenGL的庫(可以搜索如何用vs使用OpenGL的庫,可以使用vs自帶的插件或者其他方法,很方便) 要點(diǎn): 1.NET和AET的創(chuàng)建,改動(dòng) 2.改變鼠標(biāo)點(diǎn)擊和鼠標(biāo)拖拽的響應(yīng)

    2023年04月08日
    瀏覽(100)
  • 計(jì)算機(jī)圖形學(xué),OpenGL編寫的一個(gè)可實(shí)現(xiàn)旋轉(zhuǎn)縮放移動(dòng)的房間,內(nèi)有數(shù)十種交互

    計(jì)算機(jī)圖形學(xué),OpenGL編寫的一個(gè)可實(shí)現(xiàn)旋轉(zhuǎn)縮放移動(dòng)的房間,內(nèi)有數(shù)十種交互

    #include stdlib.h #includestdio.h #includewindows.h #include GL/glut.h #include math.h #include gl/GLU.h //顏色宏定義 #define white 1.0f, 1.0f, 1.0f #define black 0.0f, 0.0f, 0.0f #define red 1.0f, 0.0f, 0.0f #define blue 0.0f, 0.0f, 1.0f #define skyBlue 135.0/255.0, 206.0/255.0, 1.0f #define plum 1.0f, 187.0/255.0, 1.0f //淺紫色 #define pink 1.0f, 1

    2024年04月17日
    瀏覽(32)
  • Python+OpenCV 零基礎(chǔ)學(xué)習(xí)筆記(4-5):計(jì)算機(jī)圖形基礎(chǔ)+Python相對(duì)文件路徑+OpenCV圖像+OpenCV視頻

    Python+OpenCV 零基礎(chǔ)學(xué)習(xí)筆記(4-5):計(jì)算機(jī)圖形基礎(chǔ)+Python相對(duì)文件路徑+OpenCV圖像+OpenCV視頻

    【2022B站最好的OpenCV課程推薦】OpenCV從入門到實(shí)戰(zhàn) 全套課程 CSDN標(biāo)題里個(gè)括號(hào)對(duì)應(yīng)視頻的分P OpenCV+Python CSDN專欄 Gitee 項(xiàng)目地址 Python:3.11.5 Anaconda:23.7.4 IDE:vscode 運(yùn)行環(huán)境:Windows OpenCV:4.8.1 Python+OpenCV 零基礎(chǔ)學(xué)習(xí)筆記(1-3):anaconda+vscode+jupyter環(huán)境配置 本節(jié)課來了解以下OpenCV的簡單使用

    2024年02月03日
    瀏覽(27)
  • 計(jì)算機(jī)圖形學(xué) 期末復(fù)習(xí)筆記

    目錄 第一章-導(dǎo)論 1. 計(jì)算機(jī)圖形學(xué)的定義 2. 計(jì)算機(jī)圖形學(xué)的應(yīng)用領(lǐng)域 2.1 計(jì)算機(jī)圖形學(xué)與其他學(xué)科的關(guān)系 3. 圖形顯示器的發(fā)展及其工作原理 3.1 陰極射線管(CRT) 3.2 隨機(jī)掃描顯示器 3.3 直視存儲(chǔ)管顯示器 3.4 光柵掃描顯示器 4. 圖形軟件標(biāo)準(zhǔn)的形成 5. 三維圖形渲染管線 第二章

    2024年02月12日
    瀏覽(27)
  • Part1:使用 TensorFlow 和 Keras 的 NeRF計(jì)算機(jī)圖形學(xué)和深度學(xué)習(xí)——計(jì)算機(jī)圖形學(xué)世界中相機(jī)的工作原理

    Part1:使用 TensorFlow 和 Keras 的 NeRF計(jì)算機(jī)圖形學(xué)和深度學(xué)習(xí)——計(jì)算機(jī)圖形學(xué)世界中相機(jī)的工作原理

    是否有一種方法可以僅從一個(gè)場景多張不同視角的照片中捕獲整個(gè)3D場景? 有。 NeRF:將場景表示為用于視圖合成的神經(jīng)輻射場中(NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis),Mildenhall等人(2020)的論文解答了這個(gè)問題。NeRF的更簡單實(shí)現(xiàn)贏得了 TensorFlow社區(qū)聚光

    2024年02月07日
    瀏覽(29)
  • 《計(jì)算機(jī)系統(tǒng)2》學(xué)習(xí)筆記

    《計(jì)算機(jī)系統(tǒng)2》學(xué)習(xí)筆記

    目錄 計(jì)算機(jī)系統(tǒng)漫游 Amdahl定理 信息的表示和處理 信息存儲(chǔ) 進(jìn)制轉(zhuǎn)化 小端法 大端法 布爾代數(shù) 位級(jí)運(yùn)算 邏輯運(yùn)算 移位運(yùn)算 整數(shù)表示 無符號(hào)數(shù)編碼 補(bǔ)碼編碼 有符號(hào)數(shù)和無符號(hào)數(shù)之間的轉(zhuǎn)換 擴(kuò)展數(shù)的位表示 截?cái)鄶?shù)字 整數(shù)運(yùn)算 無符號(hào)加法 無符號(hào)數(shù)求反 有符號(hào)整數(shù)加法 補(bǔ)碼

    2024年02月11日
    瀏覽(35)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包