opengl阴影实现

cpp 复制代码
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <random>
#include <cmath>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <soil2/SOIL2.h>

const float PI = acos(-1.0f);

#include "utils.h"
#include "geometry.h"
#include "noise.h"

#include "penguin.h"

const float SPEED = 0.1f;
const float ANGLE = 0.03f;

GLuint rendering_program;
GLuint shadow_program;
GLuint plain_program;
GLuint snow_program;
GLuint sky_program;

GLuint sky_texture;
GLuint snow_texture;
GLuint shadow_depth;
GLuint shadow_buffer;
GLuint shadow_texture;

GLuint temp_location;										//临时
GLuint time_location;										//时间
GLuint global_amb_loc;

int HEIGHT = 724, WIDTH = 1024;
float aspect = (float)WIDTH / (float)HEIGHT;
float direction_light_angle = PI / 2.0f;

glm::mat4 proj_mat;
glm::vec4 global_ambient = { 0.2f, 0.2f, 0.2f, 1.0f };		//全局环境光

Camera camera;
Vertex_Manager vm;
DirectionLight sunshine;

Object* square;
Object* snow;
Object* tetrahedron;
Object* icosahedron;
Object* cube;
Object* cone;
Object* sky;
Object* sphere;
Object* water_droplet;
Object* surface;

Penguin* penguin;

enum Weather {
	sunny,
	cloudy,
	snowy
}weather;

static void SetupShadowBuffers(GLFWwindow* window) {
	GLuint buffer_id[1]{};
	glGenBuffers(1, buffer_id);
	glfwGetFramebufferSize(window, &WIDTH, &HEIGHT);
	glGenFramebuffers(1, buffer_id);
	shadow_buffer = buffer_id[0];
	glBindFramebuffer(GL_FRAMEBUFFER, shadow_buffer);
	glGenTextures(1, buffer_id);
	shadow_texture = buffer_id[0];
	glBindTexture(GL_TEXTURE_2D, shadow_texture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_texture, 0);
	glDrawBuffer(GL_COLOR_ATTACHMENT0);
	glGenTextures(1, buffer_id);
	shadow_depth = buffer_id[0];
	glBindTexture(GL_TEXTURE_2D, shadow_depth);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, WIDTH, HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_depth, 0);
}
static void init(GLFWwindow* window) {
	camera.vmat = glm::mat4(1.0f);
	camera.tmat = glm::mat4(1.0f);
	camera.rmat = glm::mat4(1.0f);
	camera.pmat = glm::perspective(1.4f, aspect, 0.2f, 500.0f);
	proj_mat = ortho_matrix(sunshine.direction, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));

	rendering_program = CreateShaderProgram("vert_shader.glsl", "frag_shader.glsl");
	shadow_program = CreateShaderProgram("shadow_vert.glsl", "shadow_frag.glsl");
	plain_program = CreateShaderProgram("plain_vert.glsl", "plain_frag.glsl");
	snow_program = CreateShaderProgram("snow_vert.glsl", "snow_frag.glsl");
	sky_program = CreateShaderProgram("sky_vert.glsl", "sky_frag.glsl");
	sky_texture = CreateNoisy3DTexture256(glm::vec4(0.0f, 0.5f, 1.0f, 1.0f), glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), MD);
	snow_texture = CreateRandom2DTexture512();
	SetupShadowBuffers(window);
	glGenVertexArrays(numVAOs, vm.vao);
	glBindVertexArray(vm.vao[0]);
	glGenBuffers(numVBOs, vm.vbo);

	glClearColor(0.7f, 0.7f, 0.7f, 1.0f);

	square = CreateSquare(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
	snow = CreateSnow(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));
	tetrahedron = CreateTetrahedron(&vm, glm::vec3(6.0f, 2.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	icosahedron = CreateIcosahedron(&vm, glm::vec3(6.0f, 4.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	cube = CreateCube(&vm, glm::vec3(6.0f, 6.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
	cone = CreateCone(&vm, glm::vec3(6.0f, 8.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 10.0f), PI / 6.0f);
	float* chunk = new float[80000];
	sky = CreateSphere(&vm, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), chunk, 80000);
	sphere = CreateSphere(&vm, glm::vec3(6.0f, 10.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), chunk, 80000);
	water_droplet = CreateWaterDroplet(&vm, glm::vec3(6.0f, 12.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), chunk, 80000);
	glm::vec3 p[4][4] = {
		glm::vec3(-1.0f,0.0f, -1.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 1.0f), glm::vec3(-1.0f, 0.0f, 2.0f),
		glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 2.0f),
		glm::vec3(1.0f, 0.0f, -1.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 2.0f),
		glm::vec3(2.0f, 0.0f, -1.0f), glm::vec3(2.0f, 0.0f, 0.0f), glm::vec3(2.0f, 0.0f, 1.0f), glm::vec3(2.0f, 0.0f, 2.0f)
	};
	surface = CreateSurface(&vm, glm::vec3(0.0f, 4.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), p, chunk, 80000);
	penguin = CreatePenguin(&vm, chunk, 80000);
	delete[] chunk;
}
static void MoveCamera(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
		camera.position[0] -= (float)sin(camera.theta) * SPEED;
		camera.position[2] -= (float)cos(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
		camera.position[0] += (float)sin(camera.theta) * SPEED;
		camera.position[2] += (float)cos(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
		camera.position[0] -= (float)cos(camera.theta) * SPEED;
		camera.position[2] += (float)sin(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
		camera.position[0] += (float)cos(camera.theta) * SPEED;
		camera.position[2] -= (float)sin(camera.theta) * SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
		camera.position[1] += SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
		camera.position[1] -= SPEED;
	}
	if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
		if (camera.phi < PI / 2.0) {
			camera.phi += ANGLE;
		}
	}
	if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
		if (camera.phi > -PI / 2.0) {
			camera.phi -= ANGLE;
		}
	}
	if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
		camera.theta += ANGLE;
	}
	if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
		camera.theta -= ANGLE;
	}
	if (glfwGetKey(window, GLFW_KEY_T) == GLFW_PRESS) {
		direction_light_angle += ANGLE;
		if (direction_light_angle >= PI) direction_light_angle -= PI * 2;
		sunshine.direction = { -cos(direction_light_angle), -0.866f * sin(direction_light_angle), -0.5f * sin(direction_light_angle)};
		proj_mat = ortho_matrix(sunshine.direction, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
		glm::vec4 m = glm::vec4(0.35f, 0.4f, 0.45f, 1.0f);
		glm::vec4 r = glm::vec4(0.35f, 0.3f, 0.25f, 0.0f);
		glm::vec4 c = m + sin(direction_light_angle) * r;
		glClearColor(c[0], c[1], c[2], c[3]);
	}
	if (glfwGetKey(window, GLFW_KEY_Y) == GLFW_PRESS) {
		weather = sunny;
	}
	if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) {
		weather = cloudy;
	}
	if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) {
		weather = snowy;
	}
	camera.tmat = glm::translate(glm::mat4(1.0f), -camera.position);
	camera.rmat = {
		{ cos(camera.theta)	 , sin(camera.phi) * sin(camera.theta) , cos(camera.phi) * sin(camera.theta)	, 0.0f },
		{ 0.0f				 , cos(camera.phi)					   , -sin(camera.phi)						, 0.0f },
		{ -sin(camera.theta) , sin(camera.phi) * cos(camera.theta) , cos(camera.phi) * cos(camera.theta)	, 0.0f },
		{ 0.0f				 , 0.0f								   , 0.0f									, 1.0f }
	};
	camera.vmat = camera.rmat * camera.tmat;
}
static void WindowReshapeCallback(GLFWwindow* window, int new_width, int new_height) {
	WIDTH = new_width;
	HEIGHT = new_height;
	aspect = (float)WIDTH / (float)HEIGHT;
	camera.pmat = glm::perspective(1.4f, aspect, 0.2f, 500.0f);
	glViewport(0, 0, WIDTH, HEIGHT);
	glDeleteTextures(1, &shadow_depth);
	glDeleteTextures(1, &shadow_texture);
	glDeleteFramebuffers(1, &shadow_buffer);
	SetupShadowBuffers(window);
}
static void InstallLight(GLuint program) {
	global_amb_loc = glGetUniformLocation(program, "GlobalAmbient");
	sunshine.dirlight_amb_loc = glGetUniformLocation(program, "DirLightAmbient");
	sunshine.dirlight_dif_loc = glGetUniformLocation(program, "DirLightDiffuse");
	sunshine.dirlight_spe_loc = glGetUniformLocation(program, "DirLightSpecular");
	sunshine.dirlight_dir_loc = glGetUniformLocation(program, "DirLightDirection");
	glProgramUniform4fv(program, global_amb_loc, 1, glm::value_ptr(global_ambient));
	glProgramUniform4fv(program, sunshine.dirlight_amb_loc, 1, glm::value_ptr(sunshine.direction_light_ambient));
	glProgramUniform4fv(program, sunshine.dirlight_dif_loc, 1, glm::value_ptr(sunshine.direction_light_diffuse));
	glProgramUniform4fv(program, sunshine.dirlight_spe_loc, 1, glm::value_ptr(sunshine.direction_light_specular));
	glProgramUniform3fv(program, sunshine.dirlight_dir_loc, 1, glm::value_ptr(sunshine.direction));
}
static void InstallShadow(GLuint shadow_program) {
	camera.vloc = glGetUniformLocation(shadow_program, "vmat");
	camera.ploc = glGetUniformLocation(shadow_program, "pmat");
	camera.mvloc = glGetUniformLocation(shadow_program, "proj");	//临时替用
}
static void InstallCamera(GLuint program) {
	camera.mvloc = glGetUniformLocation(program, "mvmat");
	camera.ploc = glGetUniformLocation(program, "pmat");
	camera.vloc = glGetUniformLocation(program, "vmat");
	camera.cloc = glGetUniformLocation(program, "texture_color");
}
static void display(GLFWwindow* window, double current_time) {
	/*第一轮:绘制阴影,记录颜色*/
	glBindFramebuffer(GL_FRAMEBUFFER, shadow_buffer);
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	glDepthFunc(GL_LEQUAL);
	glUseProgram(shadow_program);
	InstallShadow(shadow_program);
	DrawShadow(&camera, &vm, cone, proj_mat * glm::translate(glm::mat4(1.0f), cone->position));
	DrawShadow(&camera, &vm, surface, proj_mat * glm::translate(glm::mat4(1.0f), surface->position));
	DrawShadow(&camera, &vm, cube, proj_mat * glm::translate(glm::mat4(1.0f), cube->position));
	DrawShadow(&camera, &vm, tetrahedron, proj_mat * glm::translate(glm::mat4(1.0f), tetrahedron->position));
	DrawShadow(&camera, &vm, icosahedron, proj_mat * glm::translate(glm::mat4(1.0f), icosahedron->position));
	DrawShadow(&camera, &vm, sphere, proj_mat * glm::translate(glm::mat4(1.0f), sphere->position));
	DrawShadow(&camera, &vm, water_droplet, proj_mat * glm::translate(glm::mat4(1.0f), water_droplet->position));
	DrawShadow(&camera, &vm, penguin->penguin_model, proj_mat * glm::translate(glm::mat4(1.0f), penguin->penguin_model->position) *
		glm::rotate(glm::mat4(1.0f), PI, glm::vec3(0.0f, 1.0f, 0.0f)));
	/*第二轮:绘制除阴影外的物体*/
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	if (weather == sunny) {
		glUseProgram(sky_program);
		temp_location = glGetUniformLocation(sky_program, "light_angle");
		camera.vloc = glGetUniformLocation(sky_program, "light_direction");			//临时替用
		camera.mvloc = glGetUniformLocation(sky_program, "mvmat");
		camera.ploc = glGetUniformLocation(sky_program, "pmat");
		camera.mvmat = camera.vmat * glm::translate(glm::mat4(1.0f), camera.position);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_3D, sky_texture);
		glUniform1f(temp_location, direction_light_angle);
		glUniform3fv(camera.vloc, 1, glm::value_ptr(sunshine.direction));
		glUniformMatrix4fv(camera.mvloc, 1, GL_FALSE, glm::value_ptr(camera.mvmat));
		glUniformMatrix4fv(camera.ploc, 1, GL_FALSE, glm::value_ptr(camera.pmat));
		glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[sky->vbo_index[0]]);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);
		glDrawArrays(GL_TRIANGLES, 0, sky->size / 3);
	}
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	if (weather == snowy) {
		glUseProgram(snow_program);
		temp_location = glGetUniformLocation(snow_program, "camera");
		time_location = glGetUniformLocation(snow_program, "current_time");
		camera.mvloc = glGetUniformLocation(snow_program, "mvmat");
		camera.ploc = glGetUniformLocation(snow_program, "pmat");
		camera.cloc = glGetUniformLocation(snow_program, "texture_color");
		camera.mvmat = camera.vmat;
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, snow_texture);
		glUniformMatrix4fv(camera.mvloc, 1, GL_FALSE, glm::value_ptr(camera.mvmat));
		glUniformMatrix4fv(camera.ploc, 1, GL_FALSE, glm::value_ptr(camera.pmat));
		glUniform4fv(camera.cloc, 1, glm::value_ptr(snow->texture_color));
		glUniform3fv(temp_location, 1, glm::value_ptr(camera.position));
		glUniform1f(time_location, (GLfloat)current_time);
		glBindBuffer(GL_ARRAY_BUFFER, vm.vbo[snow->vbo_index[0]]);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);
		glDrawArraysInstanced(GL_TRIANGLES, 0, snow->size / 3, 262144);
	}
	glUseProgram(plain_program);
	InstallLight(plain_program);
	InstallCamera(plain_program);
	for (int x = -32; x < 32; x++) {
		for (int z = -32; z < 32; z++) {
			square->position = glm::vec3(float(x) + 0.5f, 0.0f, float(z) + 0.5f);
			square->texture_color = glm::vec4(0.0f, float((x + z) & 1), float(!bool((x + z) & 1)), 0.0f);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, shadow_texture);
			DrawObject(&camera, &vm, square);
		}
	}
	glUseProgram(rendering_program);
	InstallLight(rendering_program);
	InstallCamera(rendering_program);
	DrawObject(&camera, &vm, cone);
	DrawObject(&camera, &vm, surface);
	glEnable(GL_CULL_FACE);
	DrawObject(&camera, &vm, cube);
	DrawObject(&camera, &vm, tetrahedron);
	DrawObject(&camera, &vm, icosahedron);
	DrawObject(&camera, &vm, sphere);
	DrawObject(&camera, &vm, water_droplet);
	DrawModel(&camera, &vm, penguin->penguin_model, glm::translate(glm::mat4(1.0f), penguin->penguin_model->position) * glm::rotate(glm::mat4(1.0f), PI, glm::vec3(0.0f, 1.0f, 0.0f)));
}
int main() {
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "HelloWorld", NULL, NULL);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);
	glfwSetWindowSizeCallback(window, WindowReshapeCallback);

	init(window);
	double pre = glfwGetTime();

	while (!glfwWindowShouldClose(window)) {
		MoveCamera(window);
		display(window, pre);
		glfwSwapBuffers(window);
		glfwPollEvents();
		while (glfwGetTime() - pre <= 0.02);
		//cout << 1.0 / (glfwGetTime() - pre) << endl;			//帧率
		pre = glfwGetTime();
	}

	DestroyObject(square);
	DestroyObject(snow);
	DestroyObject(tetrahedron);
	DestroyObject(icosahedron);
	DestroyObject(cube);
	DestroyObject(cone);
	DestroyObject(sky);
	DestroyObject(sphere);
	DestroyObject(water_droplet);
	DestroyObject(surface);

	DestroyModel(penguin->penguin_model);

	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}
cpp 复制代码
shadow_vert.glsl
#version 430

layout (location=0) in vec3 position;

uniform mat4 vmat;
uniform mat4 pmat;
uniform mat4 proj;

void main(void) {
	vec4 v = proj * vec4(position, 1.0);
	gl_Position = pmat * vmat * vec4((v.xyz) / v.w, 1.0);
}
shadow_frag.glsl
#version 430

out vec4 color;

uniform mat4 mvmat;
uniform mat4 pmat;

void main(void) {
	color = vec4(1.0, 1.0, 1.0, 1.0);
}
plain_vert.glsl
#version 430

layout (location=0) in vec3 position;
layout (location=1) in vec3 normal;
layout (binding=0) uniform sampler2D sampler;

out vec3 varying_normal;
out vec3 varying_direction;
out vec3 varying_vertpos;
out vec4 glp;

uniform mat4 mvmat;
uniform mat4 pmat;
uniform mat4 vmat;
uniform vec4 texture_color;

uniform vec4 GlobalAmbient;
uniform vec4 DirLightAmbient;
uniform vec4 DirLightDiffuse;
uniform vec4 DirLightSpecular;
uniform vec3 DirLightDirection;

void main(void) {
	varying_direction = (vmat * vec4(-DirLightDirection, 0.0)).xyz;
	varying_vertpos = -(mvmat * vec4(position, 1.0)).xyz;
	varying_normal = (mvmat * vec4(normal, 0.0)).xyz;
	glp = pmat * mvmat * vec4(position, 1.0);
	gl_Position = glp;
}
plain_frag.glsl
#version 430

layout (binding=0) uniform sampler2D sampler;

in vec3 varying_normal;
in vec3 varying_direction;
in vec3 varying_vertpos;
in vec4 glp;

out vec4 color;

uniform mat4 mvmat;
uniform mat4 pmat;
uniform mat4 vmat;
uniform vec4 texture_color;

uniform vec4 GlobalAmbient;
uniform vec4 DirLightAmbient;
uniform vec4 DirLightDiffuse;
uniform vec4 DirLightSpecular;
uniform vec3 DirLightDirection;

void main(void) {
	vec3 L = normalize(varying_direction);
	vec3 N = normalize(varying_normal);
	vec3 V = normalize(varying_vertpos);
	vec3 H = normalize(L + V);
	vec4 C = texture(sampler, (vec2(glp.x, glp.y)) / (2.0 * glp.w) + vec2(0.5, 0.5));
	C[0] = float(C[0] <= 0.999);
	C[1] = float(C[1] <= 0.999);
	C[2] = float(C[2] <= 0.999);
	float cos_theta = dot(L, N);
	float cos_phi = dot(N, H);
	float flag = float(texture_color[3] <= 0.001);
	vec3 ambient = GlobalAmbient.xyz * texture_color.xyz + DirLightAmbient.xyz * texture_color.xyz;
	vec3 diffuse = C.xyz * texture_color.xyz * DirLightDiffuse.xyz * (max(cos_theta, 0.0) * (flag * 0.6 + 0.4));
	vec3 specular = C.xyz * DirLightSpecular.xyz * pow(max(cos_phi, 0.001), 3.0 * texture_color[3]) * (1.0 - flag) * 0.6;
	color = vec4(ambient + diffuse + specular, 1.0);
}
相关推荐
仰泳的熊猫2 小时前
题目 1473: 蓝桥杯基础练习VIP-芯片测试
数据结构·c++·算法·蓝桥杯
小冻梨6662 小时前
ABC444 - C 翻译
c++
拳里剑气2 小时前
C++:封装红黑树实现map和set
开发语言·数据结构·c++·学习方法
汉克老师2 小时前
GESP2024年9月认证C++二级( 第一部分选择题(1-8))
c++·算法·循环结构·分支结构·gesp二级·gesp2级
阿猿收手吧!2 小时前
【C++】syncstream:多线程安全输出的终极方案
c++·安全
「QT(C++)开发工程师」2 小时前
Day 1:信号槽原理深入
c++·qt
gfdgd xi2 小时前
GXDE OS 25.3.1 更新了!修复更多 bug 了!
linux·c++·操作系统·bug·deepin
Trouvaille ~2 小时前
【Linux】TCP vs UDP深度对比:如何选择与用UDP实现可靠传输
linux·网络·c++·tcp/ip·udp·操作系统
小比特_蓝光2 小时前
string类的模拟实现
数据结构·c++·算法