中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

新疆小程序開發(fā)商重慶網(wǎng)站seo搜索引擎優(yōu)化

新疆小程序開發(fā)商,重慶網(wǎng)站seo搜索引擎優(yōu)化,做網(wǎng)站和做程序一樣嗎,福田所有車型當(dāng)片段著色器處理完一個片段之后,模板測試(Stencil Test)會開始執(zhí)行,和深度測試一樣,它也可能會丟棄片段。接下來,被保留的片段會進(jìn)入深度測試,它可能會丟棄更多的片段。模板測試是根據(jù)又一個緩沖來進(jìn)行的,…

當(dāng)片段著色器處理完一個片段之后,模板測試(Stencil Test)會開始執(zhí)行,和深度測試一樣,它也可能會丟棄片段。接下來,被保留的片段會進(jìn)入深度測試,它可能會丟棄更多的片段。模板測試是根據(jù)又一個緩沖來進(jìn)行的,它叫做模板緩沖(Stencil Buffer),我們可以在渲染的時候更新它來獲得一些很有意思的效果。

一個模板緩沖中,(通常)每個模板值(Stencil Value)是8位的。所以每個像素/片段一共能有256種不同的模板值。我們可以將這些模板值設(shè)置為我們想要的值,然后當(dāng)某一個片段有某一個模板值的時候,我們就可以選擇丟棄或是保留這個片段了。

模板緩沖首先會被清除為0,之后在模板緩沖中使用1填充了一個空心矩形。場景中的片段將會只在片段的模板值為1的時候會被渲染(其它的都被丟棄了)。

模板緩沖操作允許我們在渲染片段時將模板緩沖設(shè)定為一個特定的值。通過在渲染時修改模板緩沖的內(nèi)容,我們寫入了模板緩沖。在同一個(或者接下來的)渲染迭代中,我們可以讀取這些值,來決定丟棄還是保留某個片段。使用模板緩沖的時候你可以盡情發(fā)揮,但大體的步驟如下:

  • 啟用模板緩沖的寫入。
  • 渲染物體,更新模板緩沖的內(nèi)容。
  • 禁用模板緩沖的寫入。
  • 渲染(其它)物體,這次根據(jù)模板緩沖的內(nèi)容丟棄特定的片段。

所以,通過使用模板緩沖,我們可以根據(jù)場景中已繪制的其它物體的片段,來決定是否丟棄特定的片段。

你可以啟用GL_STENCIL_TEST來啟用模板測試。在這一行代碼之后,所有的渲染調(diào)用都會以某種方式影響著模板緩沖。

glEnable(GL_STENCIL_TEST);

注意,和顏色和深度緩沖一樣,你也需要在每次迭代之前清除模板緩沖。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

和深度測試的glDepthMask函數(shù)一樣,模板緩沖也有一個類似的函數(shù)。glStencilMask允許我們設(shè)置一個位掩碼(Bitmask),它會與將要寫入緩沖的模板值進(jìn)行與(AND)運算。默認(rèn)情況下設(shè)置的位掩碼所有位都為1,不影響輸出,但如果我們將它設(shè)置為0x00,寫入緩沖的所有模板值最后都會變成0.這與深度測試中的glDepthMask(GL_FALSE)是等價的。?

glStencilMask(0xFF); // 每一位寫入模板緩沖時都保持原樣
glStencilMask(0x00); // 每一位在寫入模板緩沖時都會變成0(禁用寫入)

模板函數(shù)

和深度測試一樣,我們對模板緩沖應(yīng)該通過還是失敗,以及它應(yīng)該如何影響模板緩沖,也是有一定控制的。一共有兩個函數(shù)能夠用來配置模板測試:glStencilFunc和glStencilOp。

glStencilFunc(GLenum func, GLint ref, GLuint mask)一共包含三個參數(shù):

  • func:設(shè)置模板測試函數(shù)(Stencil Test Function)。這個測試函數(shù)將會應(yīng)用到已儲存的模板值上和glStencilFunc函數(shù)的ref值上??捎玫倪x項有:GL_NEVER、GL_LESS、GL_LEQUAL、GL_GREATER、GL_GEQUAL、GL_EQUAL、GL_NOTEQUAL和GL_ALWAYS。它們的語義和深度緩沖的函數(shù)類似。
  • ref設(shè)置了模板測試的參考值(Reference Value)。模板緩沖的內(nèi)容將會與這個值進(jìn)行比較。
  • mask:設(shè)置一個掩碼,它將會與參考值和儲存的模板值在測試比較它們之前進(jìn)行與(AND)運算。初始情況下所有位都為1。

在一開始的那個簡單的模板例子中,函數(shù)被設(shè)置為:

glStencilFunc(GL_EQUAL, 1, 0xFF)

這會告訴OpenGL,只要一個片段的模板值等于(GL_EQUAL)參考值1,片段將會通過測試并被繪制,否則會被丟棄。

但是glStencilFunc僅僅描述了OpenGL應(yīng)該對模板緩沖內(nèi)容做什么,而不是我們應(yīng)該如何更新緩沖。這就需要glStencilOp這個函數(shù)了。

glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)
  • sfail:模板測試失敗時采取的行為。
  • dpfail:模板測試通過,但深度測試失敗時采取的行為。
  • dppass:模板測試和深度測試都通過時采取的行為。

每個選項都可以選用以下的其中一種行為:

行為描述
GL_KEEP保持當(dāng)前儲存的模板值
GL_ZERO將模板值設(shè)置為0
GL_REPLACE將模板值設(shè)置為glStencilFunc函數(shù)設(shè)置的ref
GL_INCR如果模板值小于最大值則將模板值加1
GL_INCR_WRAP與GL_INCR一樣,但如果模板值超過了最大值則歸零
GL_DECR如果模板值大于最小值則將模板值減1
GL_DECR_WRAP與GL_DECR一樣,但如果模板值小于0則將其設(shè)置為最大值
GL_INVERT按位翻轉(zhuǎn)當(dāng)前的模板緩沖值

?默認(rèn)情況下glStencilOp是設(shè)置為(GL_KEEP, GL_KEEP, GL_KEEP)的,所以不論任何測試的結(jié)果是如何,模板緩沖都會保留它的值。

物體輪廓

所以我們將會展示一個使用模板測試就可以完成的有用特性,它叫做物體輪廓(Object Outlining)。

物體輪廓所能做的事情正如它名字所描述的那樣。我們將會為每個(或者一個)物體在它的周圍創(chuàng)建一個很小的有色邊框。當(dāng)你想要在策略游戲中選中一個單位進(jìn)行操作的,想要告訴玩家選中的是哪個單位的時候,這個效果就非常有用了。為物體創(chuàng)建輪廓的步驟如下:

  1. 在繪制(需要添加輪廓的)物體之前,將模板函數(shù)設(shè)置為GL_ALWAYS,每當(dāng)物體的片段被渲染時,將模板緩沖更新為1。
  2. 渲染物體。
  3. 禁用模板寫入以及深度測試。
  4. 將每個物體縮放一點點。
  5. 使用一個不同的片段著色器,輸出一個單獨的(邊框)顏色。
  6. 再次繪制物體,但只在它們片段的模板值不等于1時才繪制。
  7. 再次啟用模板寫入和深度測試。

這個過程將每個物體的片段的模板緩沖設(shè)置為1,當(dāng)我們想要繪制邊框的時候,我們主要繪制放大版本的物體中模板測試通過的部分,也就是物體的邊框的位置。我們主要使用模板緩沖丟棄了放大版本中屬于原物體片段的部分。

所以我們首先來創(chuàng)建一個很簡單的片段著色器,它會輸出一個邊框顏色。我們簡單地給它設(shè)置一個硬編碼的顏色值,將這個著色器命名為shaderSingleColor:

void main()
{FragColor = vec4(0.04, 0.28, 0.26, 1.0);
}

我們只想給那兩個箱子加上邊框,所以我們讓地板不參與這個過程。我們希望首先繪制地板,再繪制兩個箱子(并寫入模板緩沖),之后繪制放大的箱子(并丟棄覆蓋了之前繪制的箱子片段的那些片段)。

我們首先啟用模板測試,并設(shè)置測試通過或失敗時的行為:

glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

如果其中的一個測試失敗了,我們什么都不做,我們僅僅保留當(dāng)前儲存在模板緩沖中的值。如果模板測試和深度測試都通過了,那么我們希望將儲存的模板值設(shè)置為參考值,參考值能夠通過glStencilFunc來設(shè)置,我們之后會設(shè)置為1。

我們將模板緩沖清除為0,對箱子中所有繪制的片段,將模板值更新為1:

glStencilFunc(GL_ALWAYS, 1, 0xFF); // 所有的片段都應(yīng)該更新模板緩沖
glStencilMask(0xFF); // 啟用模板緩沖寫入
normalShader.use();
DrawTwoContainers();

通過使用GL_ALWAYS模板測試函數(shù),我們保證了箱子的每個片段都會將模板緩沖的模板值更新為1。因為片段永遠(yuǎn)會通過模板測試,在繪制片段的地方,模板緩沖會被更新為參考值。

現(xiàn)在模板緩沖在箱子被繪制的地方都更新為1了,我們將要繪制放大的箱子,但這次要禁用模板緩沖的寫入:

glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00); // 禁止模板緩沖的寫入
glDisable(GL_DEPTH_TEST);
shaderSingleColor.use(); 
DrawTwoScaledUpContainers();

我們將模板函數(shù)設(shè)置為GL_NOTEQUAL,它會保證我們只繪制箱子上模板值不為1的部分,即只繪制箱子在之前繪制的箱子之外的部分。注意我們也禁用了深度測試,讓放大的箱子,即邊框,不會被地板所覆蓋。

記得要在完成之后重新啟用深度緩沖。

場景中物體輪廓的完整步驟會看起來像這樣:

glEnable(GL_DEPTH_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glStencilMask(0x00); // 記得保證我們在繪制地板的時候不會更新模板緩沖
normalShader.use();
DrawFloor()  glStencilFunc(GL_ALWAYS, 1, 0xFF); 
glStencilMask(0xFF); 
DrawTwoContainers();glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00); 
glDisable(GL_DEPTH_TEST);
shaderSingleColor.use(); 
DrawTwoScaledUpContainers();
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);  

只要你理解了模板緩沖背后的大體思路,這個代碼片段就不是那么難理解了。如果還是不能理解的話,嘗試再次仔細(xì)閱讀之前的部分,并嘗試通過上面使用的范例,完全理解每個函數(shù)的功能。

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>#include "shader_m.h"
#include "camera.h"
#include "model.h"#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = (float)SCR_WIDTH / 2.0;
float lastY = (float)SCR_HEIGHT / 2.0;
bool firstMouse = true;// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;int main()
{// glfw: initialize and configure// ------------------------------glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif// glfw window creation// --------------------GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);// tell GLFW to capture our mouseglfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);// glad: load all OpenGL function pointers// ---------------------------------------if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// configure global opengl state// -----------------------------glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);glEnable(GL_STENCIL_TEST);glStencilFunc(GL_NOTEQUAL, 1, 0xFF);glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);// build and compile shaders// -------------------------Shader shader("/home/ss/learn/Opengl/Stencil_Test/source/2_stencil_testing.vs", "/home/ss/learn/Opengl/Stencil_Test/source/2_stencil_testing.fs");Shader shaderSingleColor("/home/ss/learn/Opengl/Stencil_Test/source/2_stencil_single_color.vs", "/home/ss/learn/Opengl/Stencil_Test/source/2_stencil_single_color.fs");// set up vertex data (and buffer(s)) and configure vertex attributes// ------------------------------------------------------------------float cubeVertices[] = {// positions          // texture Coords-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,0.5f, -0.5f, -0.5f,  1.0f, 0.0f,0.5f,  0.5f, -0.5f,  1.0f, 1.0f,0.5f,  0.5f, -0.5f,  1.0f, 1.0f,-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,0.5f, -0.5f,  0.5f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f, 1.0f,0.5f,  0.5f,  0.5f,  1.0f, 1.0f,-0.5f,  0.5f,  0.5f,  0.0f, 1.0f,-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,-0.5f,  0.5f, -0.5f,  1.0f, 1.0f,-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f, 0.0f,0.5f,  0.5f, -0.5f,  1.0f, 1.0f,0.5f, -0.5f, -0.5f,  0.0f, 1.0f,0.5f, -0.5f, -0.5f,  0.0f, 1.0f,0.5f, -0.5f,  0.5f,  0.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f, 0.0f,-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,0.5f, -0.5f, -0.5f,  1.0f, 1.0f,0.5f, -0.5f,  0.5f,  1.0f, 0.0f,0.5f, -0.5f,  0.5f,  1.0f, 0.0f,-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,0.5f,  0.5f, -0.5f,  1.0f, 1.0f,0.5f,  0.5f,  0.5f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f, 0.0f,-0.5f,  0.5f,  0.5f,  0.0f, 0.0f,-0.5f,  0.5f, -0.5f,  0.0f, 1.0f};float planeVertices[] = {// positions          // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)5.0f, -0.5f,  5.0f,  2.0f, 0.0f,-5.0f, -0.5f,  5.0f,  0.0f, 0.0f,-5.0f, -0.5f, -5.0f,  0.0f, 2.0f,5.0f, -0.5f,  5.0f,  2.0f, 0.0f,-5.0f, -0.5f, -5.0f,  0.0f, 2.0f,5.0f, -0.5f, -5.0f,  2.0f, 2.0f};// cube VAOunsigned int cubeVAO, cubeVBO;glGenVertexArrays(1, &cubeVAO);glGenBuffers(1, &cubeVBO);glBindVertexArray(cubeVAO);glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));glBindVertexArray(0);// plane VAOunsigned int planeVAO, planeVBO;glGenVertexArrays(1, &planeVAO);glGenBuffers(1, &planeVBO);glBindVertexArray(planeVAO);glBindBuffer(GL_ARRAY_BUFFER, planeVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));glBindVertexArray(0);// load textures// -------------unsigned int cubeTexture = loadTexture("/home/ss/learn/Opengl/Stencil_Test/source/marble.jpg");unsigned int floorTexture = loadTexture("/home/ss/learn/Opengl/Stencil_Test/source/metal.png");// shader configuration// --------------------shader.use();shader.setInt("texture1", 0);// render loop// -----------while (!glfwWindowShouldClose(window)){// per-frame time logic// --------------------float currentFrame = static_cast<float>(glfwGetTime());deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;// input// -----processInput(window);// render// ------glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // don't forget to clear the stencil buffer!// set uniformsshaderSingleColor.use();glm::mat4 model = glm::mat4(1.0f);glm::mat4 view = camera.GetViewMatrix();glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);shaderSingleColor.setMat4("view", view);shaderSingleColor.setMat4("projection", projection);shader.use();shader.setMat4("view", view);shader.setMat4("projection", projection);// draw floor as normal, but don't write the floor to the stencil buffer, we only care about the containers. We set its mask to 0x00 to not write to the stencil buffer.glStencilMask(0x00);// floorglBindVertexArray(planeVAO);glBindTexture(GL_TEXTURE_2D, floorTexture);shader.setMat4("model", glm::mat4(1.0f));glDrawArrays(GL_TRIANGLES, 0, 6);glBindVertexArray(0);// 1st. render pass, draw objects as normal, writing to the stencil buffer// --------------------------------------------------------------------glStencilFunc(GL_ALWAYS, 1, 0xFF);glStencilMask(0xFF);// cubesglBindVertexArray(cubeVAO);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, cubeTexture);model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));shader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);model = glm::mat4(1.0f);model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));shader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing // the objects' size differences, making it look like borders.// -----------------------------------------------------------------------------------------------------------------------------glStencilFunc(GL_NOTEQUAL, 1, 0xFF);glStencilMask(0x00);glDisable(GL_DEPTH_TEST);shaderSingleColor.use();float scale = 1.1f;// cubesglBindVertexArray(cubeVAO);glBindTexture(GL_TEXTURE_2D, cubeTexture);model = glm::mat4(1.0f);model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));model = glm::scale(model, glm::vec3(scale, scale, scale));shaderSingleColor.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);model = glm::mat4(1.0f);model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));model = glm::scale(model, glm::vec3(scale, scale, scale));shaderSingleColor.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);glStencilMask(0xFF);glStencilFunc(GL_ALWAYS, 0, 0xFF);glEnable(GL_DEPTH_TEST);// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}// optional: de-allocate all resources once they've outlived their purpose:// ------------------------------------------------------------------------glDeleteVertexArrays(1, &cubeVAO);glDeleteVertexArrays(1, &planeVAO);glDeleteBuffers(1, &cubeVBO);glDeleteBuffers(1, &planeVBO);glfwTerminate();return 0;
}// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)camera.ProcessKeyboard(FORWARD, deltaTime);if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)camera.ProcessKeyboard(BACKWARD, deltaTime);if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)camera.ProcessKeyboard(LEFT, deltaTime);if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)camera.ProcessKeyboard(RIGHT, deltaTime);
}// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{// make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays.glViewport(0, 0, width, height);
}// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{float xpos = static_cast<float>(xposIn);float ypos = static_cast<float>(yposIn);if (firstMouse){lastX = xpos;lastY = ypos;firstMouse = false;}float xoffset = xpos - lastX;float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to toplastX = xpos;lastY = ypos;camera.ProcessMouseMovement(xoffset, yoffset);
}// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{camera.ProcessMouseScroll(static_cast<float>(yoffset));
}// utility function for loading a 2D texture from file
// ---------------------------------------------------
unsigned int loadTexture(char const * path)
{unsigned int textureID;glGenTextures(1, &textureID);int width, height, nrComponents;unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);if (data){GLenum format;if (nrComponents == 1)format = GL_RED;else if (nrComponents == 3)format = GL_RGB;else if (nrComponents == 4)format = GL_RGBA;glBindTexture(GL_TEXTURE_2D, textureID);glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);stbi_image_free(data);}else{std::cout << "Texture failed to load at path: " << path << std::endl;stbi_image_free(data);}return textureID;
}

http://www.risenshineclean.com/news/27370.html

相關(guān)文章:

  • 大畫冊設(shè)計網(wǎng)站b站推廣怎么買
  • wordpress在線報名插件優(yōu)化服務(wù)
  • 響應(yīng)式網(wǎng)站背景晉城網(wǎng)站seo
  • 做網(wǎng)站建設(shè)有前途那合肥seo網(wǎng)絡(luò)營銷推廣
  • 免費建站的網(wǎng)站seo官網(wǎng)優(yōu)化
  • 建設(shè)和住房委員會官方網(wǎng)站谷歌推廣效果怎么樣
  • 完善網(wǎng)站建設(shè)信息流廣告接單平臺
  • 如何使用網(wǎng)站模板國家新聞最新消息今天
  • 蘇州滄浪做網(wǎng)站哪家好網(wǎng)站維護(hù)中
  • 連云港網(wǎng)站建設(shè)開發(fā)seo外包一共多少錢
  • 深圳寶安區(qū)什么時候解封網(wǎng)站優(yōu)化外包找誰
  • 南寧做自適應(yīng)網(wǎng)站seo推廣軟件排行榜
  • 成都哪家做網(wǎng)站濰坊新聞頭條最新消息
  • 美容院門戶網(wǎng)站開發(fā)站長之家工具
  • 常用的網(wǎng)絡(luò)營銷的手段有seo優(yōu)化工作
  • 江西省網(wǎng)站建設(shè)先進(jìn)表彰阿里巴巴運營
  • 黃頁推廣軟件網(wǎng)站武漢seo學(xué)徒
  • 中鐵建設(shè)集團(tuán)有限公司門戶網(wǎng)登錄入口seo管理平臺
  • 廊坊營銷網(wǎng)站服務(wù)百度seo優(yōu)化分析
  • 作品展示的網(wǎng)站百度下載正版
  • 網(wǎng)站怎么做移動端免費推廣神器
  • asp網(wǎng)站建設(shè)實錄源碼推廣注冊app拿傭金平臺
  • 大氣的網(wǎng)站首頁google搜索引擎入口下載
  • 加強(qiáng)網(wǎng)站政務(wù)服務(wù)建設(shè)永久免費域名申請
  • 成都b2c網(wǎng)站服裝營銷方式和手段
  • 酒店網(wǎng)站報價方案廣東網(wǎng)絡(luò)seo推廣公司
  • 獨立站和企業(yè)網(wǎng)站區(qū)別網(wǎng)絡(luò)技術(shù)培訓(xùn)
  • 個人博客網(wǎng)站制作論文網(wǎng)站關(guān)鍵詞快速排名服務(wù)
  • 軟件企業(yè)網(wǎng)站模板2023全民核酸又開始了
  • 做網(wǎng)站需要多少資金如何建立個人網(wǎng)址