您的位置:时时app平台注册网站 > web前端 > 纹理-给你叁个真正的世界【彩世界网址】

纹理-给你叁个真正的世界【彩世界网址】

2019-12-06 22:58
function initVertexBuffers(gl) {
  var verticesSizes = new Float32Array([
     0.0,  0.5,  10.0,  
    -0.5, -0.5,  20.0,  
     0.5, -0.5,  30.0   
  ]);
  var n = 3; 
  var vertexSizeBuffer = gl.createBuffer();  
  if (!vertexSizeBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  gl.bindBuffer(gl.ARRAY_BUFFER, vertexSizeBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesSizes, gl.STATIC_DRAW);

  var FSIZE = verticesSizes.BYTES_PER_ELEMENT;
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 3, 0);
  gl.enableVertexAttribArray(a_Position);  


  var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
  if(a_PointSize < 0) {
    console.log('Failed to get the storage location of a_PointSize');
    return -1;
  }
  gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE * 3, FSIZE * 2);
  gl.enableVertexAttribArray(a_PointSize);  
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  return n;
}
着色器

村办日常习贯先创立必要使用到的极端着色器和局部着色器对象,再利用glsl语言去书写着色器。前边已经涉及过,因这一片段代码是足以复用的,所以在那,我只须求调用SMShaderCompiler类中的起首化方法就可以促成着色器、着色器程序的创导,并通过着色器程序将极点着色器和局地着色器举行链接,必要传入的参数仅仅是终点着色器和朝气蓬勃部分着色器的文本名(包罗后缀)。
日后,大家便须要选取glsl语言来书写极点着色器以至部分着色器。在书写早先,我们先思忖一下,绘制叁个四边形大家须要的事物有哪些。
因为绘制的是四边形,所以多少个尖峰是必备的,可是咱们绘制的图元使用的三角形,那是还是不是须求三个极端坐标呢?答案是无需,因为大家利用EBO的点子去绘制。通过成效图大家得以很自在的获取长方形的终端坐标如下:

float vertices[] = {
    // location   
    1.0,  0.5, 0, 
    1.0, -0.5, 0, 
   -1.0, -0.5, 0,  
   -1.0,  0.5, 0
};

在授课着色器时大家谈起,书写着色器平常以版本号开首,所以大家大家先申明版本号。又大家需求三个极限坐标的输入,所以一个用于表示地点的3分量的向量是不能缺少的。为了显著地看见绘制的四边形的职能,大家再增加颜色相关的数量,那么多个意味着颜色的3份量的向量也是负有存在的必不可缺的。大家需求将极点数组中的颜色音讯传送给部分着色器,所以二个出口的颜色变量也亟需达成。为了轻便地明白地点新闻和颜色消息的岗位大家使用layout来注明。因而到那儿的极端着色器看起来就如下边同样。

#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;

out vec3 ourColor;
void main() {
    gl_Position = vec4(aPos, 1);
    ourColor = aColor;
}

对峙于极端着色器,片段着色器便轻松的多了,雷同大家注解版本音讯,并选取八个ourColor来选用极点着色器传入的颜色新闻。片段着色器看起来就是底下的表率。

#version 300 es
precision mediump float;
in vec3 ourColor;
out vec4 fragColor;

void main() {
    fragColor = vec4(ourColor, 1);
}

随着,大家就要求报告OpenGL如何解析极点数据了。

三、结尾

前提

在《Hello, OpenGL World!》和《着色器-精彩纷呈的世界,从你开首!》两篇小说过后,开采部分重新的代码,比如对于着色器、着色器程序的成立以致着色器程序链接着色器等代码。由此,将那几个重新的代码举行了简便地卷入,具体贯彻在ShaderCompiler文本夹中。后续的代码便选择该类实行着色器的部分拍卖。

var VSHADER_SOURCE =
  'attribute vec4 a_Position;n'  
  'attribute vec2 a_TexCoord;n'    // 声明一个attribute变量
  'varying vec2 v_TexCoord;n'      // 声明一个varying变量
  'void main() {n'  
  '  gl_Position = a_Position;n'  
  '  v_TexCoord = a_TexCoord;n'    // attribute变量赋给varying变量
  '}n';

var FSHADER_SOURCE =
  '#ifdef GL_ESn'  
  'precision mediump float;n'  
  '#endifn'  

  'uniform sampler2D u_Sampler;n'  
  'varying vec2 v_TexCoord;n'  
  'void main() {n'  

  // texture2D(sampler2D sampler, vec2 coord)
  // (纹理单元编号,纹理坐标) 这里是赋值的关键
  '  gl_FragColor = texture2D(u_Sampler, v_TexCoord);n'   
  '}n';

function main() {  
  var canvas = document.getElementById('webgl');
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // 设置顶点缓存
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  // 设置纹理
  if (!initTextures(gl, n)) {
    console.log('Failed to intialize the texture.');
    return;
  }
}

function initVertexBuffers(gl) {
  var verticesTexCoords = new Float32Array([
    //webgl顶点坐标, 纹理坐标相应点
    -0.5,  0.5,   0.0, 1.0,
    -0.5, -0.5,   0.0, 0.0,
     0.5,  0.5,   1.0, 1.0,
     0.5, -0.5,   1.0, 0.0,
  ]);
  var n = 4; 
  // 创建缓存区对象
  var vertexTexCoordBuffer = gl.createBuffer();
  if (!vertexTexCoordBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

  var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
  gl.enableVertexAttribArray(a_Position);  


  // 将纹理坐标分配给该存储位置并开启
  var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
  if (a_TexCoord < 0) {
    console.log('Failed to get the storage location of a_TexCoord');
    return -1;
  }  
  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
  gl.enableVertexAttribArray(a_TexCoord);  

  return n;
}

function initTextures(gl, n) {
 // Step1:设置纹理对象
  var texture = gl.createTexture();   
  if (!texture) {
    console.log('Failed to create the texture object');
    return false;
  }

  // Step2: 获取u_Sampler(取样器)存储位置
  var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
  if (!u_Sampler) {console.log('Failed to get the storage location of u_Sampler');
    return false;
  }

  // Step3: 创建图片对象
  var image = new Image();  
  if (!image) {console.log('Failed to create the image object');
    return false;
  }

  image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); };
  image.src = '../resources/sky.jpg';
  return true;
}

function loadTexture(gl, n, texture, u_Sampler, image) {
  // Step1:对图像进行y轴反转
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);  

  // Step2: 开启0号纹理单元(textunit0~7)
  gl.activeTexture(gl.TEXTURE0);

  // Step3: 绑定纹理对象(target,texture)   
  // target可以是:gl.TEXTURE或gl.TEXTURE_CUBE_MAP
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Step4: 设置纹理参数(target,pname,param)
  // gl.TEXTURE_MAG_FILTER (纹理放大) 默认值: gl.LINEAR
  // gl.TEXTURE_MIN_FILTER (纹理缩小) 默认值: gl.NEAREST_MIPMAP_LINEAR
  // gl.TEXTURE_WRAP_S (纹理水平填充)  默认值: gl.REPEAT(平铺式) 
  //                                         gl.MIRRORED_REPEAT (镜像对称)
  //                                         gl.CLAMP_TO_EDGE (使用纹理图像边缘值)
  // gl.TEXTURE_WRAP_T (纹理垂直填充)  默认值: gl.REPEAT
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

  // Step5:配置纹理图片(target,level,internalformat,format,type,image)
  // level: 0
  // internalformat:图像的内部格式
  // format: 纹理数据的格式,必须与internalformat一致
  // type: 纹理数据的类型
  // image:包含纹理的图像的image对象
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image); 

  // Step6:将0号纹理传递至取样器
  gl.uniform1i(u_Sampler, 0);

  gl.clear(gl.COLOR_BUFFER_BIT);  
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); 
}
纹理环绕情势

纹理环绕格局的用途是,当大家设置的纹理坐标当先(0,0)到(0,1)的节制时OpenGL会对纹理进行如何的拍卖。OpenGL的默许的纹理环绕方式是GL_REPEAT,看名称大家理应清楚它是何许管理的,对当先的大器晚成对实行复制。效果如下:

彩世界网址 1

GL_REPEAT纹理环绕格局

纹理的拱卫格局除了GL_REPEAT外,还有GL_MIRRORED_REPEAT、GL_CLAMP_TO_EDGE和GL_CLAMP_TO_BO凯雷德DE路虎极光那三种艺术,其意义便不豆蔻梢头风姿浪漫在那展现,我们能够把该小说的案例实现以往去校勘纹理坐标以致环绕方式开展查看。
安装纹理环绕方式我们选取glTexParameteri函数实行设置。

// 参数说明:
// target: 指定纹理目标,在这里我们绘制的是2D纹理,所以使用GL_TEXTURE_2D,当然也有1D和3D纹理
//  pname: 指定设置的选项与应用纹理坐标(s、t、r对应顶点坐标的x、y、z)
//  param: 纹理环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
var VSHADER_SOURCE =
  'attribute vec4 a_Position;n'  
  'attribute vec4 a_Color;n'    //attribute变量
  'varying vec4 v_Color;n'     // varying变量
  'void main() {n'  
  '  gl_Position = a_Position;n'  
  '  gl_PointSize = 10.0;n'  
  '  v_Color = a_Color;n'    // 将attribute变量赋给varying变量
  '}n';


var FSHADER_SOURCE =

  '#ifdef GL_ESn'  
  'precision mediump float;n'   
  '#endif GL_ESn'  

  'varying vec4 v_Color;n'      //同名varying变量
  'void main() {n'  
  '  gl_FragColor = v_Color;n'   //!!!!!
  '}n';

function initVertexBuffers(gl) {
  var verticesColors = new Float32Array([
    // 顶点坐标 与 颜色
     0.0,  0.5,  1.0,  0.0,  0.0, 
    -0.5, -0.5,  0.0,  1.0,  0.0, 
     0.5, -0.5,  0.0,  0.0,  1.0, 
  ]);
  var n = 3; 
  var vertexColorBuffer = gl.createBuffer();  
  if (!vertexColorBuffer) {
    console.log('Failed to create the buffer object');
    return false;
  }

  gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

  var FSIZE = verticesColors.BYTES_PER_ELEMENT;
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0);
  gl.enableVertexAttribArray(a_Position);  
  var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
  if(a_Color < 0) {
    console.log('Failed to get the storage location of a_Color');
    return -1;
  }
  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
  gl.enableVertexAttribArray(a_Color);  

  return n;
}
正文

大家曾经大概驾驭了有的着色器的学识,而OpenGL超过八分之四视觉神奇的级差是在一些着色器阶段,片段着色器的为主方面既是对表面应用纹理。
大家通过使用OpenGL来绘制一张图纸到显示屏上来具体学习纹理的某些知识点。末了大家绘制的图片如下效果。

彩世界网址 2

终极效果

我们绘制一张星型的图样,那张图纸是“贴”上去的,所以,大家能够选拔后面使用的文化先绘制一个正方形,这里本人也会呈报如何绘制二个正方形,从而深化对日前知识的精通。

 

GL_LINEAHaval(线性过滤)

线性过滤会基于纹理坐标左近的纹路像素总括出七个插值,相仿出那么些纹理像素的颜色,四个纹理像素的为主间隔纹理坐标的偏离越近,该纹理像素所占的比例越大。

彩世界网址 3

线性过滤 图来源于LearOpenGL CN

设置纹理的过滤格局也是应用glTexParameteri函数,只是传入的值分裂而已。这里大家联合行使GL_NEAREST的过滤方式。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

在后边早就收获了多少个分包地方、颜色、纹理坐标的终端数组,所以这里大家须要对终极着色器甚至一些着色器实行对应的修正。
大家对纹理采集样本并赢得对应纹理坐标的纹路像素,而纹理坐标在我们的顶峰数组中定义的是叁个2轻重的向量,在后生可畏部分着色器中,我们风流洒脱致需求纹理坐标来收获纹理像素的颜料,所以这里便多出多个一个纹理坐标的输入和出口,那么极端着色器也就成为了上边包车型地铁范例。

#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 ourTexCoord;

void main() {
    gl_Position = vec4(aPos, 1);
    ourColor = aColor;
    ourTexCoord = aTexCoord;
}

在有的着色器中大家本来须要一个2份额的向量来选择极点着色器的纹路坐标的输入。此外,我们还要掌握对应的纹理来进行着色,在此边我们使用uniform的点子来安装。在main函数中,使用texture函数来收获终极的水彩。

#version 300 es
precision mediump float;

in vec2 ourTexCoord;
in vec3 ourColor;
out vec4 fragColor;

uniform sampler2D ourTexture;

void main() {
    fragColor = texture(ourTexture, ourTexCoord);
}

在改过完着色器后,紧接着便要改革链接极点属性相关的代码了。这里关键因为扩充了纹路坐标,所以大家的步进值由6化为了8,在下标为2时,偏移量为3

  • 3 = 6。因而,设置VAO...函数的代码如下:

    float vertices[] = {

      // location    // colors       // texture
      1.0,  0.5, 0,  1.0, 0.0, 0.0,  2.0, 2.0,
      1.0, -0.5, 0,  0.0, 1.0, 0.0,  2.0, 0.0,
     -1.0, -0.5, 0,  0.0, 0.0, 1.0,  0.0, 0.0,
     -1.0,  0.5, 0,  1.0, 1.0, 1.0,  0.0, 2.0
    

    };

    GLuint indices[] = {

      0, 1, 3,
      1, 2, 3
    

    };

    glGenVertexArrays(1, &(_VAO)); glBindVertexArray(_VAO);

    glGenBuffers(1, &(_VBO)); glBindBuffer(GL_ARRAY_BUFFER, _VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &(_EBO)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 sizeof(float), (void )0); glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 sizeof(float), (void )(3 * sizeof(float))); glEnableVertexAttribArray(1);

    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 sizeof(float), (void )(6 * sizeof(float))); glEnableVertexAttribArray(2);

到这里,大家还未有对纹理做别的的管理,只是设置了它的缠绕格局和过滤情势。以往我们要转移和利用纹理。生成纹理和选择纹理的上学大家能够参照VAO、VBO、EBO。因为它们的步调是这么的相像。
变化纹理:

glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);

是还是不是很VBO等拾叁分相仿?同样地在前边,大家供给对纹理实行绑定,使用glTexImage2D方法就可以。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

终极,正是实体的渲染,在渲染函数中,大家绑定VAO以致纹理,再经过绘制三角形的章程实行渲染就能够。

glClearColor(0.2, 0.5, 0.8, 1);
glClear(GL_COLOR_BUFFER_BIT);

glBindTexture(GL_TEXTURE_2D, _texture);
[self.shaderCompiler userProgram];
glBindVertexArray(_VAO);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

纹理贴图就到位了。假诺你成功这里运路程序后并从未拿走与效果与利益图中的结果,请参见源码。

       Example3:纹理(将图片的纹路赋给webgl对象)

GL_NEAREST(左近过滤)

将近过滤指的是OpenGL会接受宗旨点最临近于纹理坐标的百般像素。

彩世界网址 4

亲临其境过滤 图来源于LearOpenGL CN

        

纹理过滤

纹理过滤是报告OpenGL怎么样将纹理像素映射到纹理坐标。OpenGL有成都百货上千纹理过滤的选项,在这里大家临时只表达GL_NEAREST(左近过滤)和GL_LINEAPAJERO(线性过滤)三种。

      到底到了第五章了,貌似发轫一发复杂了。

后续

在持续的篇章中,会新开贰个专项论题总计一些微电脑图形学根底有关的学识,当然笔者也是边学边总计,若有难堪之处,尽请提议,相互学习提升。

 

绘图正方形的步子

1.安装上下文
2.设置着色器
3.设置VAO、VBO、EBO(IBO)
4.革除窗口在这里早先渲染

 

上下文

安装上下文相关在此就不做赘述了,千篇风华正茂律的设置。查占星关函数就能够。

        **Example1**:使用叁个缓冲区去赋值多个尖峰数据(富含坐标及点大小)

VAO、VBO、EBO

在前面大家已经书写出了矩形的终点坐标,再增多颜色相关的音信,极点数据就成了下边包车型地铁样子。

float vertices[] = {
    // location    // colors       
    1.0,  0.5, 0,  1.0, 0.0, 0.0,  
    1.0, -0.5, 0,  0.0, 1.0, 0.0,  
   -1.0, -0.5, 0,  0.0, 0.0, 1.0,  
   -1.0,  0.5, 0,  1.0, 1.0, 1.0
};

因为我们运用EBO的主意去贯彻矩形的绘图,所以大家必要掌握绘制矩形的目录(索引须要凭仗极点数据之处音信并以0最初):

GLuint indices[] = {
    0, 1, 3,
    1, 2, 3
};

下边正是VAO、VBO、EBO的扭转绑定了,这里便不做赘述,直接贴代码。

glGenVertexArrays(1, &(_VAO));
glBindVertexArray(_VAO);

glGenBuffers(1, &(_VBO));
glBindBuffer(GL_ARRAY_BUFFER, _VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glGenBuffers(1, &(_EBO));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

然后正是报告OpenGL如何分析极点数据了。通过剖析极点数据大家能够剖判到与坐标相关的地点音讯起头于0,颜色发轫于1,因为大家在极端着色器里是那般写的。数据类型当然是float类型,并且步进值很醒目是6,地方的偏移量是0,颜色的偏移量是3 * sizeof(float卡塔尔国。那么链接极点属性的代码看起来是这么的。

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

提及底正是渲染了。这里没有怎么相比为难驾驭的东西,所以一贯贴代码。

glClearColor(0.2, 0.5, 0.8, 1);
glClear(GL_COLOR_BUFFER_BIT);

[self.shaderCompiler userProgram];
glBindVertexArray(_VAO);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

运路程序,大家便足以见到绘制出三个美好的矩形了。

彩世界网址 5

天时地利的矩形

上边大家便开端纹理相关文化的疏解:
个体明白,将图片贴入到显示屏上,是将图片上的一一点的水彩举办采样(使用纹理坐标获取纹理颜色),并让极点实行关联。纹理相像持有纹理坐标,纹理坐标的限制是0-1,伊始于(0,0),终止于(1,1)。

彩世界网址 6

纹理坐标

在这里案例中,大家把左下角的坐标设置为(0,0),那么右下方向上的纹理坐标则为(1, 0),右上方向上的纹路坐标则为(1, 1),左上方向上的纹理坐标则为(1, 1)。我们把纹理坐标写入顶点数组,那么被涂改后的顶峰数组如下:

float vertices[] = {
    // location    // colors       // texture
    1.0,  0.5, 0,  1.0, 0.0, 0.0,  1.0, 1.0,
    1.0, -0.5, 0,  0.0, 1.0, 0.0,  1.0, 0.0,
   -1.0, -0.5, 0,  0.0, 0.0, 1.0,  0.0, 0.0,
   -1.0,  0.5, 0,  1.0, 1.0, 1.0,  0.0, 1.0
};

赢得纹理坐标以往,大家便要告诉OpenGL如何对纹理进行采样了。

二、正文

          Example2:使用varying变量从终端着色器传输颜色消息给片元着色器

      以上代码均源于《WebGL编制程序指南》。

一、前言

 

本文由时时app平台注册网站发布于web前端,转载请注明出处:纹理-给你叁个真正的世界【彩世界网址】

关键词: