首页 > 其他分享 >WebGL之缩放(基础)

WebGL之缩放(基础)

时间:2024-01-24 22:33:20浏览次数:31  
标签:const 缩放 WebGL 基础 shader program vec2 gl image

一, index.html

<body>
	<script id="vertex-shader-2d" type="notjs">
		attribute vec2 a_position;
		attribute vec2 a_texCoord;
		uniform vec2 u_resolution;
		uniform vec2 u_translation;
		uniform vec2 u_rotation;//旋转全局变量
		uniform vec2 u_scale;//缩放
		varying vec2 v_texCoord;
		
		vec2 getRotationValue(vec2 position,vec2 rotation){
			return vec2(
				position.x*rotation.y + position.y*rotation.x,
				position.y*rotation.y - position.x*rotation.x
			);
		}
		
		void main(){
			vec2 position = getRotationValue(a_position * u_scale,u_rotation) + u_translation;//位置偏移
			v_texCoord = a_texCoord;
			// 从像素坐标转换到 0.0 到 1.0
			vec2 zeroToOne = position.xy / u_resolution;
			// 再把 0->1 转换 0->2
			vec2 zeroToTwo = zeroToOne * 2.0;
			// 把 0->2 转换到 -1->+1 (剪裁空间)
			vec2 clipSpace = zeroToTwo - 1.0;
			
			gl_Position = vec4(clipSpace* vec2(1, -1),0,1);
		}


</script>
	<script id="fragment-shader-2d" type="notjs">
		precision mediump float;
		uniform sampler2D u_image;
		varying vec2 v_texCoord;
		void main(){
			gl_FragColor = texture2D(u_image, v_texCoord);
		}
</script>
	<script src="js/shader5.js"></script>
</body>

二, shader.js

function getRotation(angle) {
	let rotation = [];
	const angleInRadians = angle * Math.PI / 180;
	rotation[0] = Math.sin(angleInRadians);
	rotation[1] = Math.cos(angleInRadians);
	return rotation;
}

/**
 * 加载图片
 * @param imageName
 * @param pork
 * @param callback
 */
function loadImage(imageName, pork, callback) {
	const image = new Image();
	image.src = "http://127.0.0.1:" + pork + "/WebGLDemo/textures/" + imageName;
	image.onload = () => {
		callback(image);
	};
}


function setTexture(gl, image) {
	const texture = gl.createTexture();
	gl.bindTexture(gl.TEXTURE_2D, texture);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); //gl.LINEAR
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); //gl.NEAREST
	gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
}

function setRectangle(gl, x, y, width, height) {
	const x1 = x;
	const x2 = x + width;
	const y1 = y;
	const y2 = y + height;
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
		x1, y1,
		x2, y1,
		x1, y2,
		x1, y2,
		x2, y1,
		x2, y2,
	]), gl.STATIC_DRAW);
}


/**
 * 获得绘图上下文gl WebGLRenderingContext
 * @param {Object} width
 * @param {Object} height
 */
function getWebGLRenderingContext(width, height) {
	const canvas = document.createElement("canvas");
	document.getElementsByTagName("body")[0].appendChild(canvas);

	canvas.width = width;
	canvas.height = height;

	const gl = canvas.getContext("webgl");
	if (!gl) {
		console.log("%c不支持webgl", "color:#F00");
		return null;
	}
	return gl;
}

function getShaderSource(isVertex) {
	let source;
	if (isVertex) {
		source = document.querySelector("#vertex-shader-2d").text;
	} else {
		source = document.querySelector("#fragment-shader-2d").text;
	}
	return source;
}

/**
 * @param {Object} gl WebGLReanderingContext
 * @param {Object} type gl.VERTEX_SHADER/gl.FRAGMENT_SHADER
 * @param {Object} source source string
 */
function createShader(gl, type, source) {
	const shader = gl.createShader(type); //创建相关类型的shader
	gl.shaderSource(shader, source); //提供shader的资源
	gl.compileShader(shader); //编译shader
	const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
	if (success) {
		return shader;
	}
	console.log(gl.getShaderInfoLog(shader));
	gl.deleteShader(shader);
}

/**
 * 链接(link)2个shader,得到着色程序program
 * @param {Object} gl WebGLReanderingContext
 * @param {Object} vertexShader 顶点着色器
 * @param {Object} fragmentShader 片段着色器
 */
function createProgram(gl, vertexShader, fragmentShader) {
	const program = gl.createProgram();
	gl.attachShader(program, vertexShader);
	gl.attachShader(program, fragmentShader);
	gl.linkProgram(program);
	const success = gl.getProgramParameter(program, gl.LINK_STATUS);
	if (success) {
		return program;
	}
	console.log(gl.getProgramInfoLog(program));
	gl.deleteProgram(program);
}

function render(gl, program, image) {
	const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
	const texCoordAttributeLocation = gl.getAttribLocation(program, "a_texCoord");
	const resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution");
	const translationUniformLocation = gl.getUniformLocation(program, "u_translation");
	const rotationUniformLocation = gl.getUniformLocation(program, "u_rotation");
	const scaleUniformLocation = gl.getUniformLocation(program, "u_scale");

	const positionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
	setRectangle(gl, 0, 0, image.width, image.height); //矩形(2个三角形)


	const texCoordBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
		0.0, 0.0,
		1.0, 0.0,
		0.0, 1.0,
		0.0, 1.0,
		1.0, 0.0,
		1.0, 1.0
	]), gl.STATIC_DRAW);

	//开始渲染
	gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
	gl.clearColor(0, 0, 0, 0);
	gl.clear(gl.COLOR_BUFFER_BIT);

	gl.useProgram(program);
	// uniform: 设置全局属性
	gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);


	gl.enableVertexAttribArray(positionAttributeLocation);
	gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
	const size = 2; //每次迭代运行提取2个单位数据
	const type = gl.FLOAT; //每个单位数据是32位的浮点数
	const normaliza = false; //不需要归一化数据
	const stride = 0; //0 = 移动单位数量 * 每个单位占用的内存(sizeof(type))
	const offset = 0; //每次迭代运行运动多少内存到下一个数据开始点,从缓冲起始位置开始读取
	gl.vertexAttribPointer(positionAttributeLocation, size, type, normaliza, stride, offset);

	gl.enableVertexAttribArray(texCoordAttributeLocation);
	gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
	gl.vertexAttribPointer(texCoordAttributeLocation, 2, gl.FLOAT, false, 0, 0);


	setTexture(gl, image);


	const primitiveType = gl.TRIANGLES; //绘制三角形
	const pOffset = 0; //从第一个点开始绘制
	const count = 6; //绘制6个点(运行6次)

	let angle = 50;
	let scale = 0.7;
	let isScaleAdd = true;
	setInterval(() => {
		if (isScaleAdd) {
			scale += 0.01;
			if (scale >= 1.4) {
				isScaleAdd = false;
			}
		} else {
			scale -= 0.01;
			if (scale <= 0.7) {
				isScaleAdd = true;
			}
		}
		gl.uniform2fv(translationUniformLocation, [150, 150]);
		gl.uniform2fv(rotationUniformLocation, getRotation(angle));
		gl.uniform2fv(scaleUniformLocation, [scale, scale]);
		gl.drawArrays(primitiveType, pOffset, count);
	}, 15);
}

function main() {
	const WIDTH = 400;
	const HEIGHT = 300;
	const gl = getWebGLRenderingContext(WIDTH, HEIGHT);
	if (!gl) return;
	//#region 构建2个shader
	const vertexShader = createShader(gl, gl.VERTEX_SHADER, getShaderSource(true));
	const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, getShaderSource(false));
	//#endregion

	//#region link2个shader
	const program = createProgram(gl, vertexShader, fragmentShader);
	//#endregiopn
	loadImage("cocos.png", 8848, (image) => {
		render(gl, program, image);
	});
}

main();

三, 结果 

WebGL之缩放(基础)_基础

标签:const,缩放,WebGL,基础,shader,program,vec2,gl,image
From: https://blog.51cto.com/aonaufly/9402863

相关文章

  • 《设计模式:可复用面向对象软件的基础》PDF
    内容简介本书结合设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中*有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好、表达清楚的软件设计模式,这些模式在实用环境下特别有用。本书适合大学计算机专业的学生、研究生及相关人......
  • 3. 基础概念
    基础概念函数:一段能被反复调用的代码,可以接收输入,进行处理并(或)产生输出如下就是一个简单的打印Helloworld!的代码:hello.cpp#include<iostream>intmain(void){std::cout<<"Helloworld!\n";return0;}返回类型:表示了函数返回结果的类型,可以为void......
  • CV 基础知识学习笔记
    简略记录一下一些基本的CV的知识参考:https://www.bilibili.com/video/BV1q7411T7Y6/输出层计算公式:\(out_{size}=(in_{size}-F_{size}+2P)/S+1\)\(in_{size}\)为输入长度\(F_{size}\)为权重矩阵长度,减掉意义为去掉第一个矩阵长度。\(P\)为padding,即填充长......
  • Java基础(一)
    文章目录第一章、java环境搭建1.1、Java介绍1.1.1、Java开发平台1.1.2、Java开发环境搭建1.1.3、Java专业术语1.1.4、第一个Java程序1.1.5、练习1.2、main方法1.3、变量1.3.1、变量介绍1.3.2、练习1.3.3、变量名规范1.3.4、注释1.4、数据类型......
  • 韩顺平java基础-13-常用类
    韩顺平java基础-13-常用类常用类包装类分类装箱和拆箱//自动装箱intn1=100;Integerinteger=intn1;//自动调用Integer.valueOf(n1)的方法//自动拆箱intn2=integer;//自动调用integer.intValue的方法包装类与String转换包装类型--->String类toString()......
  • NanoFramework操作ESP32(一)_基础元器件篇(二十二)_DHT11温湿度传感器
    一、元器件介绍1、针脚用途编号名称功能1VCC电源正2TRIG触发控制信号输入3ECHO回响信号输出4GND电源地2、电气参数 二、示例代码1、代码:元器件的针脚ESP32模块的针脚VCC;供电脚+5VTRIG;发送脚IO17ECHO;接收脚IO16GND......
  • vue基础指令
    Vue基础指令CDN使用VUE对于制作原型或学习,你可以这样使用最新版本:<scriptsrc="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:<scriptsrc="https://cdn.jsdelivr......
  • Linux网络编程基础API
    目录socket地址API创建socket命名socket监听socket接收连接发起连接关闭连接数据读写带外标记地址信息函数socket选项网络信息APIsocket地址API主机字节序和网络字节序在Linux系统中,主机字节序(HostByteOrder)和网络字节序(NetworkByteOrder)是两个重要的概念。主机字节序......
  • Linux基础46 ansible概述, 结构, 安装与配置文件, 主机清单配置
    Ansible学习一、Ansible概述1.什么是ansible?Ansible是一个自动化统一配置管理工具,自动化主要体现在Ansible集成了丰富模块以及功能组件,可以通过一个命令完成一系列的操作,进而能减少重复性的工作和维护成本,可以提高工作效率。2.自动化工具1.puppet学习难,安装ruby环境难,没......
  • Python三方库:Pika(RabbitMQ基础使用)
    Python有多种插件都支持RabbitMQ,本文介绍的是RabbitMQ推荐的Pika插件。使用pip直接安装即可pipinstallpika。一、RabbitMQ简介1.MQ简介MQ(MessageQueue,消息队列),是一个在消息传输过程中保存消息的容器,多用在分布式系统之间进行通信。MQ优势应用解耦:提高系统容错性和可......