目录
Texture Wrapping:UV超过了[0,1]怎么办?
Texture Filter:UV经过计算得到的是浮点数怎么办?
Texture Unit——OpenGL提供了多个Texture锚定点,显示多个纹理图
初识——纹理系统是什么?怎么用?
Texture —— UV坐标系统
- UV坐标定义到每一个顶点上
- 通过插值,到纹理图片上采样
- 得到像素点颜色
Texture Wrapping:UV超过了[0,1]怎么办?
OpenGL提供了几种方式,如图
Texture Filter:UV经过计算得到的是浮点数怎么办?
Texture Filter的结果以及相关情况下的设置
也就是说在纹理变小的时候,采用Nearest进行采样;纹理变大的时候,采用Linear方式采样。
在OpenGL中该怎么做呢?
①在C++当中创建Texture,并且绑定到系统中进行渲染和数据传递
②在shader中进行处理
Texture Unit——OpenGL提供了多个Texture锚定点,显示多个纹理图
整理代码、建立ffImage类
新建ffImage.h及ffImage.cpp
//ffImage.h
#pragma once
#include "Base.h"
class ffImage
{
private:
int m_width;
int m_height;
int m_picType;
ffRGBA* m_data;
public:
int getWidth()const { return m_width; }
int getHeight()const { return m_height; }
int getPicType()const { return m_picType; }
ffRGBA* getData()const { return m_data; }
ffRGBA getColor(int x, int y)const {
if (x<0 || x>m_width - 1 || y<0 || y>m_height - 1) {
return ffRGBA(0, 0, 0, 0);
}
return m_data[y * m_width + x];
}
ffImage(int _width = 0, int _height = 0, int _picType = 0, ffRGBA* _data = nullptr) {
m_width = _width;
m_height = _height;
m_picType = _picType;
int _sumSize = m_width * m_height;
if (_data && _sumSize) {
m_data = new ffRGBA[_sumSize];
memcpy(m_data, _data, sizeof(ffRGBA) * _sumSize);
}
else {
m_data = nullptr;
}
}
~ffImage() {
if (m_data) {
delete[]m_data;
}
}
public:
static ffImage* readFromFile(const char* _fileName);
};
//ffImage.cpp
#include "ffImage.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
ffImage* ffImage::readFromFile(const char* _fileName)
{
int _picType = 0;
int _width = 0;
int _height = 0;
//stbimage读入图片是反过来的
stbi_set_flip_vertically_on_load(true);
unsigned char* bits = stbi_load(_fileName, &_width, &_height, &_picType, STBI_rgb_alpha);
ffImage* _image = new ffImage(_width, _height, _picType, (ffRGBA*)bits);
stbi_image_free(bits);
return _image;
}
Texture纹理的应用
同样的,建立一个句柄:
unsigned int _texture = 0;
纹理的相关处理:
void initTexture() {
_pImage = ffImage::readFromFile("res/wall.jpg");
//纹理绑定
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
//纹理属性设置
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//读入图片数据
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _pImage->getWidth(), _pImage->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,_pImage->getData());
}
同样的,需要在顶点数组中添加UV信息:
float vertices[] = {
//顶点信息 颜色信息 纹理信息
0.5f, 0.5f, 0.0f, 1.0f,0.0f,0.0f, 1.0f,1.0f,
0.5f, -0.5f, 0.0f, 0.0f,1.0f,0.0f, 1.0f,0.0f,
-0.5f, -0.5f, 0.0f, 0.0f,0.0f,1.0f, 0.0f,0.0f,
-0.5f, 0.5f, 0.0f, 0.0f,1.0f,0.0f, 0.0f,1.0f
};
同样的,新建一个锚点(layout):
//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float)*3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float)*6));
同样的,激活这个锚点2
//打开锚点:激活
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
同样的,更新一下shader
//vertexShader.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aUV;
out vec4 outColor;
out vec2 outUV;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
outColor = vec4(aColor, 1.0f);
outUV = aUV;
};
//fragmentShader.glsl
#version 330 core
out vec4 FragColor;
in vec4 outColor;
in vec2 outUV;
uniform sampler2D outTexture;
void main()
{
FragColor = texture(outTexture, outUV);
};
这里值得注意一点,在fragmentShader中的sampler2D,这里并没有通过C++的代码传入数据,因为我们只用了一张纹理贴图,默认texture unit为0,而这个sampler2D也是默认取为0的texture unit
渲染结果:
混合结果:
//fragmentShader.glsl
#version 330 core
out vec4 FragColor;
in vec4 outColor;
in vec2 outUV;
uniform sampler2D outTexture;
void main()
{
FragColor = texture(outTexture, outUV) * outColor;
};