OpenGL原理与实践——核心模式(三):Texture-纹理系统理论与应用

目录

初识——纹理系统是什么?怎么用?

Texture —— UV坐标系统

Texture Wrapping:UV超过了[0,1]怎么办?

Texture Filter:UV经过计算得到的是浮点数怎么办?

在OpenGL中该怎么做呢?

Texture Unit——OpenGL提供了多个Texture锚定点,显示多个纹理图

整理代码、建立ffImage类

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;
};

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值