IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++/OpenGL 入门(10):实例化24个/10万个立方体同时运动 -> 正文阅读

[C++知识库]C++/OpenGL 入门(10):实例化24个/10万个立方体同时运动

  1. 来源:《Computer Graphics Programming in OpenGL Using C++ 》by V Scott Gordon John L Clevenger
  2. 内容:程序4.2 Instancing – Twenty-Four Animated Cubes,书P80页,PDF99/403
  3. 相关介绍可参考OpenGL–用一个立方体实例化为10万个立方体
  4. 这里参考了OpenGL–用一个立方体实例化为10万个立方体的 vertShader.glsl 和 fragShader.glsl 两份文件
    结果,生成多个转动的彩色立方体,如下

实例化10万个/24个立方体同时运动

生成24个立方体同时运动

  1. 文件1: 4.2 instancing.cpp
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>


#include "glm\glm.hpp"
#include "glm\gtc\type_ptr.hpp"
#include "glm\gtc\matrix_transform.hpp"
#include "Utils\4.1 Utils.h"
using namespace std;
#define numVAOs 1
#define numVBOs 2
float cameraX, cameraY, cameraZ;
float cubeLocX, cubeLocY, cubeLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];

// allocate variables used in display() function, 
// so that they won’t need to be allocated during rendering
GLuint mvLoc, projLoc,vLoc,tfLoc;
int width, height;
float aspect, timeFactor;
glm::mat4 pMat, vMat, mMat, mvMat;
glm::mat4 tMat, rMat;//为了动画而添加的内容

void setupVertices(void) {
	// 36 vertices, 12 triangles, makes 2x2x2 cube placed at origin
	float vertexPositions[108] = {
	 -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
	 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
	 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
	 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
	 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
	 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
	 -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
	 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f
	};
	glGenVertexArrays(1, vao);
	glBindVertexArray(vao[0]);
	glGenBuffers(numVBOs, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
}
void init(GLFWwindow* window) {

	//renderingProgram = createShaderProgram("add/4.1 vertShader.glsl", "add/4.1 fragShader.glsl");
	renderingProgram = createShaderProgram("add/4.2 vertShader.glsl", "add/4.2 fragShader.glsl");
	cameraX = 0.0f; cameraY = 0.0f; cameraZ = 32.0f;//24个立方体对应z=32,10万个对应420
	//cubeLocX = 0.0f; cubeLocY = -2.0f; cubeLocZ = 0.0f; // shift down Y to reveal perspective
	setupVertices();
}

void display(GLFWwindow* window, double currentTime) {
	glClear(GL_DEPTH_BUFFER_BIT);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT); // 每一次都将背景清理(clear)为黑色
	glUseProgram(renderingProgram);
	// get the uniform variables for the MV and projection matrices
	vLoc = glGetUniformLocation(renderingProgram, "v_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
	// build perspective matrix
	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f); // 1.0472 radians = 60 degrees
	glUniformMatrix4fv(vLoc, 1, GL_FALSE, glm::value_ptr(vMat)); // shader needs the V matrix
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
															 // build view matrix, model matrix, and model-view matrix

	timeFactor = ((float)currentTime); // uniform for the time factor
	tfLoc = glGetUniformLocation(renderingProgram, "tf"); // (the shader needs that too)
	glUniform1f(tfLoc, (float)timeFactor);

	// associate VBO with the corresponding vertex attribute in the vertex shader
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
	// adjust OpenGL settings and draw model
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 24);// 24---24个立方体,100000---10万个立方体
}

int main(void) { // main() is unchanged from before
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(600, 600, "Chapter 4 - program 1", NULL, NULL);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);
	init(window);
	while (!glfwWindowShouldClose(window)) {
		display(window, glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}
  1. 文件2: 4.2 vertShader.glsl 参考OpenGL–用一个立方体实例化为10万个立方体的即可运行
#version 430

layout (location=0) in vec3 position;

uniform mat4 v_matrix;
uniform mat4 proj_matrix;
uniform float tf;//用于动画和放置立方体的时间因子

out vec4 varyingColor;

mat4 buildRotateX(float rad);//矩阵变换工具函数的声明
mat4 buildRotateY(float rad);//glsl要求函数先声明后调用
mat4 buildRotateZ(float rad);
mat4 buildTranslate(float x,float y,float z);

void main(void)
{
	float i=gl_InstanceID+tf; //取值基于时间因子,但是对每个立方体示例也都不同的。

	float a=sin(0.35*i)*8.0; //这些是用来平移的x,y,z分量,24个的时候
	float b=sin(0.52*i)*8.0;
	float c=sin(0.70*i)*8.0;

	//float a=sin(203.0*i/8000.0)*403.0; //这些是用来平移的x,y,z分量
	//float b=sin(301.0*i/4001.0)*401.0;
	//float c=sin(400.0*i/6003.0)*405.0;

	//构建旋转和平移矩阵,将会应用于当前立方体的模型矩阵
	mat4 localRotX=buildRotateX(0.1*i);
	mat4 localRotY=buildRotateY(0.1*i);
	mat4 localRotZ=buildRotateZ(0.1*i);
	mat4 localTrans=buildTranslate(a,b,c);

	//构建模型矩阵,然后是模型-视图矩阵
	mat4 newM_matrix=localTrans*localRotX*localRotY*localRotZ;
	mat4 mv_matrix=v_matrix*newM_matrix;
	gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
	varyingColor = vec4(position,1.0)*0.5+vec4(0.5,0.5,0.5,0.5);
} 

//构建平移矩阵的工具函数(来自第三章)
mat4 buildTranslate(float x,float y,float z)
{
	mat4 trans=mat4(1.0,0.0,0.0,0.0,
	0.0,1.0,0.0,0.0,
	0.0,0.0,1.0,0.0,
	x,y,z,1.0);
	return trans;
}
//用来绕x,y,z轴旋转的类似函数
mat4 buildRotateX(float rad)
{
	mat4 trans=mat4(
	1.0,0.0,0.0,0.0,
	0.0,cos(rad),-sin(rad),0.0,
	0.0,sin(rad),cos(rad),0.0,
	0.0,0.0,0.0,1.0);
	return trans;
}
mat4 buildRotateY(float rad)
{
	mat4 trans=mat4(
	cos(rad),0.0,sin(rad),0.0,
	0.0,1.0,0.0,0.0,
	-sin(rad),0.0,cos(rad),0.0,
	0.0,0.0,0.0,1.0);
	return trans;
}
mat4 buildRotateZ(float rad)
{
	mat4 trans=mat4(
	cos(rad),sin(rad),0.0,0.0,
	-sin(rad),cos(rad),0.0,0.0,
	0.0,0.0,1.0,0.0,
	0.0,0.0,0.0,1.0);
	return trans;
}
3. 文件24.2 fragShader.glsl 参考[OpenGL--用一个立方体实例化为10万个立方体](https://blog.csdn.net/weixin_44210987/article/details/108173586?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164432910416780271963614%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164432910416780271963614&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-108173586.pc_search_insert_es_download&utm_term=opengl%20%E7%AB%8B%E6%96%B9%E4%BD%93%20%E5%AE%9E%E4%BE%8B%E5%8C%96&spm=1018.2226.3001.4187)的即可运行

```cpp
#version 430

in vec4 varyingColor;
out vec4 color;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

void main(void)
{	color = varyingColor;
}


生成10万个立方体同时运动

  1. 文件1: 4.2 instancing.cpp
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>


#include "glm\glm.hpp"
#include "glm\gtc\type_ptr.hpp"
#include "glm\gtc\matrix_transform.hpp"
#include "Utils\4.1 Utils.h"
using namespace std;
#define numVAOs 1
#define numVBOs 2
float cameraX, cameraY, cameraZ;
float cubeLocX, cubeLocY, cubeLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];

// allocate variables used in display() function, 
// so that they won’t need to be allocated during rendering
GLuint mvLoc, projLoc,vLoc,tfLoc;
int width, height;
float aspect, timeFactor;
glm::mat4 pMat, vMat, mMat, mvMat;
glm::mat4 tMat, rMat;//为了动画而添加的内容

void setupVertices(void) {
	// 36 vertices, 12 triangles, makes 2x2x2 cube placed at origin
	float vertexPositions[108] = {
	 -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
	 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
	 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
	 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
	 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
	 -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
	 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
	 -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
	 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f
	};
	glGenVertexArrays(1, vao);
	glBindVertexArray(vao[0]);
	glGenBuffers(numVBOs, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
}
void init(GLFWwindow* window) {

	//renderingProgram = createShaderProgram("add/4.1 vertShader.glsl", "add/4.1 fragShader.glsl");
	renderingProgram = createShaderProgram("add/4.2 vertShader.glsl", "add/4.2 fragShader.glsl");
	cameraX = 0.0f; cameraY = 0.0f; cameraZ = 420.0f;//24个立方体对应z=32,10万个对应420
	//cubeLocX = 0.0f; cubeLocY = -2.0f; cubeLocZ = 0.0f; // shift down Y to reveal perspective
	setupVertices();
}

void display(GLFWwindow* window, double currentTime) {
	glClear(GL_DEPTH_BUFFER_BIT);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT); // 每一次都将背景清理(clear)为黑色
	glUseProgram(renderingProgram);
	// get the uniform variables for the MV and projection matrices
	vLoc = glGetUniformLocation(renderingProgram, "v_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
	// build perspective matrix
	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f); // 1.0472 radians = 60 degrees
	glUniformMatrix4fv(vLoc, 1, GL_FALSE, glm::value_ptr(vMat)); // shader needs the V matrix
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
															 // build view matrix, model matrix, and model-view matrix

	timeFactor = ((float)currentTime); // uniform for the time factor
	tfLoc = glGetUniformLocation(renderingProgram, "tf"); // (the shader needs that too)
	glUniform1f(tfLoc, (float)timeFactor);
	
	// associate VBO with the corresponding vertex attribute in the vertex shader
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
	// adjust OpenGL settings and draw model
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 100000);// 24个立方体,或改为10万个立方体
}

int main(void) { // main() is unchanged from before
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(600, 600, "Chapter 4 - program 1", NULL, NULL);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);
	init(window);
	while (!glfwWindowShouldClose(window)) {
		display(window, glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}
  1. 文件2: 4.2 vertShader.glsl 参考OpenGL–用一个立方体实例化为10万个立方体的即可运行
#version 430

layout (location=0) in vec3 position;

uniform mat4 v_matrix;
uniform mat4 proj_matrix;
uniform float tf;//用于动画和放置立方体的时间因子

out vec4 varyingColor;

mat4 buildRotateX(float rad);//矩阵变换工具函数的声明
mat4 buildRotateY(float rad);//glsl要求函数先声明后调用
mat4 buildRotateZ(float rad);
mat4 buildTranslate(float x,float y,float z);

void main(void)
{
	float i=gl_InstanceID+tf; //取值基于时间因子,但是对每个立方体示例也都不同的。

	//float a=sin(0.35*i)*8.0; //这些是用来平移的x,y,z分量,24个的时候
	//float b=sin(0.52*i)*8.0;
	//float c=sin(0.70*i)*8.0;

	float a=sin(203.0*i/8000.0)*403.0; //这些是用来平移的x,y,z分量
	float b=sin(301.0*i/4001.0)*401.0;
	float c=sin(400.0*i/6003.0)*405.0;

	//构建旋转和平移矩阵,将会应用于当前立方体的模型矩阵
	mat4 localRotX=buildRotateX(0.1*i);
	mat4 localRotY=buildRotateY(0.1*i);
	mat4 localRotZ=buildRotateZ(0.1*i);
	mat4 localTrans=buildTranslate(a,b,c);

	//构建模型矩阵,然后是模型-视图矩阵
	mat4 newM_matrix=localTrans*localRotX*localRotY*localRotZ;
	mat4 mv_matrix=v_matrix*newM_matrix;
	gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
	varyingColor = vec4(position,1.0)*0.5+vec4(0.5,0.5,0.5,0.5);
} 

//构建平移矩阵的工具函数(来自第三章)
mat4 buildTranslate(float x,float y,float z)
{
	mat4 trans=mat4(1.0,0.0,0.0,0.0,
	0.0,1.0,0.0,0.0,
	0.0,0.0,1.0,0.0,
	x,y,z,1.0);
	return trans;
}
//用来绕x,y,z轴旋转的类似函数
mat4 buildRotateX(float rad)
{
	mat4 trans=mat4(
	1.0,0.0,0.0,0.0,
	0.0,cos(rad),-sin(rad),0.0,
	0.0,sin(rad),cos(rad),0.0,
	0.0,0.0,0.0,1.0);
	return trans;
}
mat4 buildRotateY(float rad)
{
	mat4 trans=mat4(
	cos(rad),0.0,sin(rad),0.0,
	0.0,1.0,0.0,0.0,
	-sin(rad),0.0,cos(rad),0.0,
	0.0,0.0,0.0,1.0);
	return trans;
}
mat4 buildRotateZ(float rad)
{
	mat4 trans=mat4(
	cos(rad),sin(rad),0.0,0.0,
	-sin(rad),cos(rad),0.0,0.0,
	0.0,0.0,1.0,0.0,
	0.0,0.0,0.0,1.0);
	return trans;
}


  1. 文件2: 4.2 fragShader.glsl 参考OpenGL–用一个立方体实例化为10万个立方体的即可运行 (与生成24个立方体的相同,无需修改)
#version 430

in vec4 varyingColor;
out vec4 color;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

void main(void)
{	color = varyingColor;
}


改变立方体的数量,需要更改的部分

  1. 4.2 instancing.cpp中,主要改两个地方
    init 函数:
    cameraX = 0.0f; cameraY = 0.0f; cameraZ = 32.0f; //24个立方体时对应z=32
    cameraX = 0.0f; cameraY = 0.0f; cameraZ = 420.0f; //10万个立方体时对应z=420
    display 函数:
    glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 24); // 24个立方体,
    glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 100000); // 10万个立方体

  2. 4.2 vertShader.glsl
    如果是10万个立方体:
    //float a=sin(0.35*i)8.0; //这些是用来平移的x,y,z分量,24个的时候
    //float b=sin(0.52
    i)8.0;
    //float c=sin(0.70
    i)*8.0;

float a=sin(203.0*i/8000.0)*403.0; //这些是用来平移的x,y,z分量
float b=sin(301.0*i/4001.0)*401.0;
float c=sin(400.0*i/6003.0)*405.0;

如果是24个立方体:
float a=sin(0.35*i)8.0; //这些是用来平移的x,y,z分量,24个的时候
float b=sin(0.52
i)8.0;
float c=sin(0.70
i)*8.0;

//float a=sin(203.0*i/8000.0)*403.0; //这些是用来平移的x,y,z分量
//float b=sin(301.0*i/4001.0)*401.0;
//float c=sin(400.0*i/6003.0)*405.0;
  1. 4.2 fragShader.glsl文件中不需要更改
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-09 20:30:34  更:2022-02-09 20:31:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:44:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码