【无标题】

1)纹理坐标

纹理坐标范围0-1,左下角(0,0),右上角(0,1),使用纹理坐标获取纹理颜色叫做采样。

2)纹理环绕方式

如果纹理坐标超过0-1,OpenGL提供了几种环绕方式:

可以用glTexParameter函数来设置:


  
  
  1. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
  2. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

如果选择了GL_CLAMP_TO_BORDER,可以用以下代码设置颜色:


  
  
  1. float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
  2. glTexParameterfv(GL_TEXTURE_ 2D, GL_TEXTURE_BORDER_COLOR, borderColor);

3)纹理过滤

当纹理和物体相差很大时,会涉及到纹理缩放,通过以下代码来设置缩放选项:


  
  
  1. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  2. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

4)多级渐远纹理

可使用glGenerateMipmaps创建多级渐远纹理。

在渲染中切换多级渐远纹理级别(Level)时,OpenGL在两个不同级别的多级渐远纹理层之间会产生不真实的生硬边界。就像普通的纹理过滤一样,切换多级渐远纹理级别时你也可以在两个不同多级渐远纹理级别之间使用NEAREST和LINEAR过滤。为了指定不同多级渐远纹理级别之间的过滤方式,你可以使用下面四个选项中的一个代替原有的过滤方式:

一个常见的错误是,将放大过滤的选项设置为多级渐远纹理过滤选项之一。这样没有任何效果,因为多级渐远纹理主要是使用在纹理被缩小的情况下的。

 5)加载纹理

图片格式多种多样,可以用stb_image.h(下载)库来加载图片。加入以下两行代码,预处理器会修改头文件,让其只包含相关的函数定义源码。


  
  
  1. #define STB_IMAGE_IMPLEMENTATION
  2. #include "stb_image.h"

使用stbi_load加载图片:


  
  
  1. int width, height, nrChannels;
  2. unsigned char * data = stbi_load( "container.jpg", &width, &height, &nrChannels, 0);

6)生成纹理

创建并绑定纹理:


  
  
  1. unsigned int texture;
  2. glGenTextures( 1, &texture);
  3. glBindTexture(GL_TEXTURE_ 2D, texture);

用图片图片数据生成纹理:


  
  
  1. glTexImage 2D(GL_TEXTURE_ 2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
  2. glGenerateMipmap(GL_TEXTURE_ 2D);
  • 第一个参数指定了纹理目标(Target)。设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理(任何绑定到GL_TEXTURE_1D和GL_TEXTURE_3D的纹理不会受到影响)。

  • 第二个参数为纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别。

  • 第三个参数告诉OpenGL我们希望把纹理储存为何种格式。我们的图像只有RGB值,因此我们也把纹理储存为RGB值。

  • 第四个和第五个参数设置最终的纹理的宽度和高度。我们之前加载图像的时候储存了它们,所以我们使用对应的变量。

  • 下个参数应该总是被设为0(历史遗留的问题)。

  • 第七第八个参数定义了源图的格式和数据类型。我们使用RGB值加载这个图像,并把它们储存为char(byte)数组,我们将会传入对应值。

  • 最后一个参数是真正的图像数据。

生成一个纹理的过程:


  
  
  1. unsigned int texture;
  2. glGenTextures( 1, &texture);
  3. glBindTexture(GL_TEXTURE_ 2D, texture);
  4. / / 为当前绑定的纹理对象设置环绕、过滤方式
  5. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  6. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  7. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  8. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  9. / / 加载并生成纹理
  10. int width, height, nrChannels;
  11. unsigned char * data = stbi_load( "container.jpg", &width, &height, &nrChannels, 0);
  12. if ( data)
  13. {
  14. glTexImage 2D(GL_TEXTURE_ 2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
  15. glGenerateMipmap(GL_TEXTURE_ 2D);
  16. }
  17. else
  18. {
  19. std ::cout < < "Failed to load texture" < < std ::endl;
  20. }
  21. stbi_image_ free( data);

7)应用纹理


  
  
  1. float vertices[] = {
  2. / / ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
  3. 0. 5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, / / 右上
  4. 0. 5f, - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, / / 右下
  5. - 0.5f, - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, / / 左下
  6. - 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f / / 左上
  7. };
  8. glVertexAttribPointer( 2, 2, GL_FLOAT, GL_ FALSE, 8 * sizeof(float), (void *)( 6 * sizeof(float)));
  9. glEnableVertexAttribArray( 2);

顶点着色器:


  
  
  1. #version 330 core
  2. layout ( location = 0) in vec 3 aPos;
  3. layout ( location = 1) in vec 3 aColor;
  4. layout ( location = 2) in vec 2 aTexCoord;
  5. out vec 3 ourColor;
  6. out vec 2 TexCoord;
  7. void main()
  8. {
  9. gl_Position = vec 4(aPos, 1.0);
  10. ourColor = aColor;
  11. TexCoord = aTexCoord;
  12. }

片段着色器:


  
  
  1. #version 330 core
  2. out vec 4 FragColor;
  3. in vec 3 ourColor;
  4. in vec 2 TexCoord;
  5. uniform sampler 2D ourTexture;
  6. void main()
  7. {
  8. FragColor = texture(ourTexture, TexCoord);
  9. }

8)纹理单元

使用glUniform1i,我们可以给纹理采样器分配一个位置值,这样的话我们能够在一个片段着色器中设置多个纹理。一个纹理的位置值通常称为一个纹理单元(Texture Unit)。一个纹理的默认纹理单元是0,它是默认的激活纹理单元。其它的纹理单元使用时要激活。


  
  
  1. glActiveTexture(GL_TEXTURE 0); / / 在绑定纹理之前先激活纹理单元
  2. glBindTexture(GL_TEXTURE_ 2D, texture 1);
  3. glActiveTexture(GL_TEXTURE 1);
  4. glBindTexture(GL_TEXTURE_ 2D, texture 2);
  5. glBindVertexArray(VAO);
  6. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

片段着色器:


  
  
  1. #version 330 core
  2. ...
  3. uniform sampler 2D texture 1;
  4. uniform sampler 2D texture 2;
  5. void main()
  6. {
  7. FragColor = mix(texture(texture 1, TexCoord), texture(texture 2, TexCoord), 0.2);
  8. }

通过glUniform1i设置纹理单元:


  
  
  1. glUniform 1i(glGetUniformLocation(ourShader.ID, "texture1"), 0); / / 手动设置
  2. glUniform 1i(glGetUniformLocation(ourShader.ID, "texture2"), 1); / / 手动设置

图片可能会上下颠倒,这是因为OpenGL要求y轴0.0坐标是在图片的底部的,但是图片的y轴0.0坐标通常在顶部。用一下代码可以反转图片:

stbi_set_flip_vertically_on_load(true);

  
  

9)源码示例


  
  
  1. int ma in()
  2. {
  3. / / build and compile our shader zprogram
  4. / / ------------------------------------
  5. Shader ourShader( "4.2.texture.vs", "4.2.texture.fs");
  6. / / set up vertex data ( and buffer(s)) and configure vertex attributes
  7. / / ------------------------------------------------------------------
  8. float vertices[] = {
  9. / / positions / / colors / / texture coords
  10. 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, / / top right
  11. 0.5f, - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, / / bottom right
  12. - 0.5f, - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, / / bottom left
  13. - 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f / / top left
  14. };
  15. unsigned int indices[] = {
  16. 0, 1, 3, / / first triangle
  17. 1, 2, 3 / / second triangle
  18. };
  19. unsigned int VBO, VAO, EBO;
  20. glGenVertexArrays( 1, &VAO);
  21. glGenBuffers( 1, &VBO);
  22. glGenBuffers( 1, &EBO);
  23. glBindVertexArray(VAO);
  24. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  25. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  26. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
  27. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  28. / / position attribute
  29. glVertexAttribPointer( 0, 3, GL_FLOAT, GL_ FALSE, 8 * sizeof(float), (void *) 0);
  30. glEnableVertexAttribArray( 0);
  31. / / color attribute
  32. glVertexAttribPointer( 1, 3, GL_FLOAT, GL_ FALSE, 8 * sizeof(float), (void *)( 3 * sizeof(float)));
  33. glEnableVertexAttribArray( 1);
  34. / / texture coord attribute
  35. glVertexAttribPointer( 2, 2, GL_FLOAT, GL_ FALSE, 8 * sizeof(float), (void *)( 6 * sizeof(float)));
  36. glEnableVertexAttribArray( 2);
  37. / / load and create a texture
  38. / / -------------------------
  39. unsigned int texture 1, texture 2;
  40. / / texture 1
  41. / / ---------
  42. glGenTextures( 1, &texture 1);
  43. glBindTexture(GL_TEXTURE_ 2D, texture 1);
  44. / / set the texture wrapping parameters
  45. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_WRAP_S, GL_REPEAT); / / set texture wrapping to GL_REPEAT ( default wrapping method)
  46. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  47. / / set texture filtering parameters
  48. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  49. glTexParameteri(GL_TEXTURE_ 2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  50. / / load image, create texture and generate mipmaps
  51. int width, height, nrChannels;
  52. stbi_ set_flip_vertically_ on_load( true); / / tell stb_image.h to flip loaded texture 's on the y-axis.
  53. // The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
  54. unsigned char *data = stbi_load(FileSystem::getPath("resources/textures/container.jpg").c_str(), &width, &height, &nrChannels, 0);
  55. if (data)
  56. {
  57. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
  58. glGenerateMipmap(GL_TEXTURE_2D);
  59. }
  60. else
  61. {
  62. std::cout << "Failed to load texture" << std::endl;
  63. }
  64. stbi_image_free(data);
  65. // texture 2
  66. // ---------
  67. glGenTextures(1, &texture2);
  68. glBindTexture(GL_TEXTURE_2D, texture2);
  69. // set the texture wrapping parameters
  70. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
  71. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  72. // set texture filtering parameters
  73. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  74. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  75. // load image, create texture and generate mipmaps
  76. data = stbi_load(FileSystem::getPath("resources/textures/awesomeface.png").c_str(), &width, &height, &nrChannels, 0);
  77. if (data)
  78. {
  79. // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
  80. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  81. glGenerateMipmap(GL_TEXTURE_2D);
  82. }
  83. else
  84. {
  85. std::cout << "Failed to load texture" << std::endl;
  86. }
  87. stbi_image_free(data);
  88. // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
  89. // -------------------------------------------------------------------------------------------
  90. ourShader.use(); // don't forget to activate / use the shader before setting uniforms!
  91. / / either set it manually like so:
  92. glUniform 1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
  93. / / or set it via the texture class
  94. ourShader.setInt( "texture2", 1);
  95. / / render loop
  96. / / -----------
  97. while ( 1)
  98. {
  99. / / render
  100. / / ------
  101. glClearColor( 0.2f, 0.3f, 0.3f, 1.0f);
  102. glClear(GL_COLOR_BUFFER_ BIT);
  103. / / bind textures on corresponding texture units
  104. glActiveTexture(GL_TEXTURE 0);
  105. glBindTexture(GL_TEXTURE_ 2D, texture 1);
  106. glActiveTexture(GL_TEXTURE 1);
  107. glBindTexture(GL_TEXTURE_ 2D, texture 2);
  108. / / render container
  109. ourShader. use();
  110. glBindVertexArray(VAO);
  111. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  112. }
  113. / / optional: de-allocate all resources once they 've outlived their purpose:
  114. // ------------------------------------------------------------------------
  115. glDeleteVertexArrays(1, &VAO);
  116. glDeleteBuffers(1, &VBO);
  117. glDeleteBuffers(1, &EBO);
  118. return 0;
  119. }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值