gpt4 book ai didi

javascript - WebGL 渲染像素化线条

转载 作者:行者123 更新时间:2023-12-02 23:49:53 26 4
gpt4 key购买 nike

我尝试渲染简单的形状(圆形、矩形和三 Angular 形),但是,当 WebGL 渲染它们时,它们会变得非常像素化。

着色器代码:

<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;

uniform vec2 u_resolution;

void main() {
// convert the rectangle points from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;

// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;

// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;

gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;

uniform vec4 u_color;

void main() {
gl_FragColor = u_color;
}
</script>

这是我渲染圆的代码:

var WebGLRenderer = (function () {

function WebGLRenderer() {
this.canvas = document.getElementById('canvas')
this.gl = this.canvas.getContext('webgl') || this.canvas.getContext('experimental-webgl')
if (!this.gl) {
throw Error('Your browser does not support WebGL')
return
}

// Programs
this.rectangleProgram = webglUtils.createProgramFromScripts(this.gl, ['2d-vertex-shader', '2d-fragment-shader'])

// Locations
this.rectanglePoisitionLocation = this.gl.getAttribLocation(this.rectangleProgram, 'a_position')

// Uniforms
this.rectangleResolutionLocation = this.gl.getUniformLocation(this.rectangleProgram, 'u_resolution')
this.rectangleColorLocation = this.gl.getUniformLocation(this.rectangleProgram, 'u_color')

// this.positionBuffer = this.gl.createBuffer()
this.rectanglePositionBuffer = this.gl.createBuffer()
// this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer)

requestAnimationFrame(this.render.bind(this))
}


WebGLRenderer.prototype.clearCanvas = function (color) {
var rgba = color.getColor()
this.gl.clearColor(...rgba)
this.gl.clear(this.gl.COLOR_BUFFER_BIT)
}

WebGLRenderer.prototype.drawCircle = function (x, y, radius, color) {
// Render circle
// For now user rectangleProgram
this.gl.useProgram(this.rectangleProgram)
this.gl.enableVertexAttribArray(this.rectanglePoisitionLocation)
// this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer)
this.circleBuffer = this.gl.createBuffer()
// this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.rectanglePositionBuffer)
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.circleBuffer)

// Setup circle
var circleVertices = [x, y]
var numFans = 360
var anglePerFan = (2 * Math.PI) / numFans
for (var i = 0; i <= numFans; i++) {
var angle = anglePerFan * (i + 1)
var angledX = x + Math.cos(angle) * radius
var angledY = y + Math.sin(angle) * radius
circleVertices.push(angledX, angledY)
// circleVertices.push()
}
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(circleVertices), this.gl.DYNAMIC_DRAW)
// this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(positions), this.gl.STATIC_DRAW)

var size = 2
var type = this.gl.FLOAT
var normalize = false
var stride = 0
var offset = 0
this.gl.vertexAttribPointer(this.rectanglePoisitionLocation, size, type, normalize, stride, offset)

this.gl.uniform2f(this.rectangleResolutionLocation, this.gl.canvas.width, this.gl.canvas.height)

// Color
var colorArray = color.getColor()
this.gl.uniform4fv(this.rectangleColorLocation, colorArray)

// Draw rectangle
var primitiveType = this.gl.TRIANGLE_FAN
// var primitiveType = this.gl.POINTS
var offset = 0
var count = circleVertices.length / size
// var count = positions.length / size
this.gl.drawArrays(primitiveType, offset, count)
}

WebGLRenderer.prototype.render = function (time) {
this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height)

var delta = Math.sin(time / 1000) * 10
this.clearCanvas(new Color(0, 0, 0, 255))
var rectangleColor = new Color(0, 65, 255, 255)
var width = 50
var height = 50
var circleColor = new Color(0, 167, 255, 255)
this.drawCircle(10, 10, 10, circleColor)

requestAnimationFrame(this.render.bind(this))
}
return WebGLRenderer
})()


function Color(r, g, b, a) {
this.r = r
this.g = g
this.b = b
this.a = a
this.getColor = function () {
return [r / 255, g / 255, b / 255, a / 255]
}
}

var renderer = new WebGLRenderer()

结果:模糊的圆圈(我用 WebGL 渲染的所有内容都是模糊的)

查看 fiddle 结果:https://jsfiddle.net/xLwmngav/1/

预期结果:平滑的圆

感谢任何帮助。预先感谢您。

最佳答案

正如this article中指出的那样 Canvas 有两种尺寸:它们的分辨率(其中有多少像素)和它们显示的尺寸。

通常您希望分辨率匹配或超过 Canvas 显示的尺寸。最好的方法是在渲染之前检查 Canvas 的分辨率是否与其显示的大小相匹配,以及是否不使用这样的函数调整其大小

  function resize(canvas) {
// Lookup the size the browser is displaying the canvas.
const desiredWidth = canvas.clientWidth;
const desiredHeight = canvas.clientHeight;

// Check if the canvas is not the same size.
if (canvas.width !== desiredWidth ||
canvas.height !== desiredHeight) {

// Make the canvas the same size
canvas.width = desiredWidth;
canvas.height = desiredHeight;
}
}

像这样使用它

function render() {
resize(canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

... draw here ...

...

示例:

function resize(canvas) {
// Lookup the size the browser is displaying the canvas.
const desiredWidth = canvas.clientWidth;
const desiredHeight = canvas.clientHeight;

// Check if the canvas is not the same size.
if (canvas.width !== desiredWidth ||
canvas.height !== desiredHeight) {

// Make the canvas the same size
canvas.width = desiredWidth;
canvas.height = desiredHeight;
}
}

var WebGLRenderer = (function () {

function WebGLRenderer() {
this.canvas = document.getElementById('canvas')
this.gl = this.canvas.getContext('webgl') || this.canvas.getContext('experimental-webgl')
if (!this.gl) {
throw Error('Your browser does not support WebGL')
return
}

// Programs
this.rectangleProgram = webglUtils.createProgramFromScripts(this.gl, ['2d-vertex-shader', '2d-fragment-shader'])

// Locations
this.rectanglePoisitionLocation = this.gl.getAttribLocation(this.rectangleProgram, 'a_position')

// Uniforms
this.rectangleResolutionLocation = this.gl.getUniformLocation(this.rectangleProgram, 'u_resolution')
this.rectangleColorLocation = this.gl.getUniformLocation(this.rectangleProgram, 'u_color')

// this.positionBuffer = this.gl.createBuffer()
this.rectanglePositionBuffer = this.gl.createBuffer()
// this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer)

requestAnimationFrame(this.render.bind(this))
}


WebGLRenderer.prototype.clearCanvas = function (color) {
var rgba = color.getColor()
this.gl.clearColor(...rgba)
this.gl.clear(this.gl.COLOR_BUFFER_BIT)
}

WebGLRenderer.prototype.drawCircle = function (x, y, radius, color) {
// Render circle
// For now user rectangleProgram
this.gl.useProgram(this.rectangleProgram)
this.gl.enableVertexAttribArray(this.rectanglePoisitionLocation)
// this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer)
this.circleBuffer = this.gl.createBuffer()
// this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.rectanglePositionBuffer)
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.circleBuffer)

// Setup circle
var circleVertices = [x, y]
var numFans = 360
var anglePerFan = (2 * Math.PI) / numFans
for (var i = 0; i <= numFans; i++) {
var angle = anglePerFan * (i + 1)
var angledX = x + Math.cos(angle) * radius
var angledY = y + Math.sin(angle) * radius
circleVertices.push(angledX, angledY)
// circleVertices.push()
}
/*var circleVertices = [
x, y,
15, 18,
5, 18,
0, 10,
4, 1,
14, 1,
20, 9,
15, 18
]*/
// three 2d points
// TODO: Research static draw
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(circleVertices), this.gl.DYNAMIC_DRAW)
// this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(positions), this.gl.STATIC_DRAW)

var size = 2
var type = this.gl.FLOAT
var normalize = false
var stride = 0
var offset = 0
this.gl.vertexAttribPointer(this.rectanglePoisitionLocation, size, type, normalize, stride, offset)

this.gl.uniform2f(this.rectangleResolutionLocation, this.gl.canvas.width, this.gl.canvas.height)

// Color
var colorArray = color.getColor()
this.gl.uniform4fv(this.rectangleColorLocation, colorArray)

// Draw rectangle
var primitiveType = this.gl.TRIANGLE_FAN
// var primitiveType = this.gl.POINTS
var offset = 0
var count = circleVertices.length / size
// var count = positions.length / size
this.gl.drawArrays(primitiveType, offset, count)
}

WebGLRenderer.prototype.render = function (time) {
resize(this.gl.canvas);
this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height)

var delta = Math.sin(time / 1000) * 10
this.clearCanvas(new Color(0, 0, 0, 255))
var rectangleColor = new Color(0, 65, 255, 255)
var width = 50
var height = 50
var circleColor = new Color(0, 167, 255, 255)
this.drawCircle(10, 10, 10, circleColor)

requestAnimationFrame(this.render.bind(this))
}
return WebGLRenderer
})()


function Color(r, g, b, a) {
this.r = r
this.g = g
this.b = b
this.a = a
this.getColor = function () {
return [r / 255, g / 255, b / 255, a / 255]
}
}

var renderer = new WebGLRenderer()

window.WebGLRenderer = WebGLRenderer
body {
margin: 0;
}

#canvas {
display: block; /* prevents scrollbar */
width: 100vw;
height: 100vh;
}
<canvas id="canvas"></canvas>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;

uniform vec2 u_resolution;

void main() {
// convert the rectangle points from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;

// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;

// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;

gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;

uniform vec4 u_color;

void main() {
gl_FragColor = u_color;
}
</script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/m3.js"></script>

关于javascript - WebGL 渲染像素化线条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55694010/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com