LiveServer 的 HTTP 服务器对本机提供 5500 端口的页面服务,即 http://localhost:5500/index.html先上效果,后面再解析片元着色器:

html 部分就简单一些
<canvas id="c" width="600" height="600" style="border: 1px solid darkseagreen;"></canvas>
<script type="module" src="./main.js"></script>
不出意外的话,你可以看到一个带暗绿色边框的 canvas,长宽均为 600 像素。
JavaScript 代码也比较简单,省略大部分动态代码和有无判断代码:
const canvas = document.getElementById('c')
const shaderText = `/* 着色器代码,后面会给 */`
const init = async () => {
const adapter = await navigation.gpu.requestAdapter()
const device = await adapter.requestDevice()
const context = canvas.getContext('webgpu')
const presentationFormat = context.getPreferredFormat(adapter)
context.configure({
device,
format: presentationFormat,
size: [ 600, 600 ], // canvas 的画图尺寸
})
const pipeline = device.createRenderPipeline({
vertex: {
module: device.createShaderModule({
code: shaderText
}),
entryPoint: 'vertexMain'
},
fragment: {
module: device.createShaderModule({
code: shaderText
}),
entryPoint: 'fragmentMain',
targets: [{ format: presentationFormat }],
},
primitive: { topology: 'triangle-list' },
})
const render = () => {
/*
每帧创建编码器并“录制”编码过程,最终提交给设备
*/
const commandEncoder = device.createCommandEncoder()
const textureView = context.getCurrentTexture().createView()
const renderPassDescriptor = {
colorAttachments: [
{
view: textureView,
clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
loadOp: 'clear',
storeOp: 'store',
},
],
}
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor)
passEncoder.setPipeline(pipeline)
passEncoder.draw(3, 1, 0, 0)
passEncoder.end()
device.queue.submit([commandEncoder.finish()])
requestAnimationFrame(render)
}
requestAnimationFrame(render)
} // async function init
init()
我保留了完整的 rAF 帧动画结构。
为了方便说明内置在片元着色器中的帧缓冲坐标变量,我将三角形顶点值写死在顶点着色器中,见下文。
着色器代码:
const shaderText = /* wgsl */`
@stage(vertex)
fn vertexMain(
@builtin(vertex_index) VertexIndex: u32
) -> @builtin(position) vec4<f32> {
var pos = array<vec2<f32>, 3>(
vec2<f32>(0.0, 0.5),
vec2<f32>(-0.5, -0.5),
vec2<f32>(0.5, -0.5)
);
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
}
@stage(fragment)
fn fragmentMain(
@builtin(position) FrameBufferCoord: vec4<f32>
) -> @location(0) vec4<f32> {
var color = vec4<f32>(1.0, 0.5, 0.0, .5);
let x: f32 = (FrameBufferCoord.x - 300.0) / 300.0;
let y: f32 = (-FrameBufferCoord.y + 300.0) / 300.0;
let r: f32 = sqrt(x * x + y * y);
if (x > -0.1 && x < 0.1) {
return vec4<f32>(1.0, 0.0, 0.5, 1.0);
} else if (y > -0.1 && y < 0.1) {
return vec4<f32>(0.0, 0.5, 1.0, 1.0);
} else if (r < 0.4) {
return vec4<f32>(FrameBufferCoord.rgb / 600.0, 0.5);
} else {
discard;
}
}
`
WGSL 褒贬不一,就不说它的语法如何了。
主要是看片元着色器的输入,@builtin(position) FrameBufferCoord: vec4<f32>,它向每一个片元着色器传入了当前片元的帧缓冲坐标,类型是 vec4<f32>
帧缓冲在 WebGPU 规范中有说明,它的坐标轴、原点和坐标值域是这样的:

我对帧缓冲坐标进行了缩放、平移,也就是计算了 x、y,将原点移动到 canvas 中央,然后把坐标区间从 [0, 600] 映射到 [-1, 1]。
然后就是最后的那个多步逻辑分支了,也很简单:
[0, 1]),加了 0.5 的透明度discard 丢弃,即不渲染OK,今天就学到这里。
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内
我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token
是否有可能以某种方式访问Class.new范围内的a?a=5Class.new{defb;aend}.new.b#NameError:undefinedlocalvariableormethod`a'for#:0x007fa8b15e9af0>#:in`b' 最佳答案 即使@MarekLipka的回答是正确的——改变变量范围总是有风险的。这是可行的,因为每个block都带有创建它的上下文,因此您的局部变量a突然变得不那么局部了——它变成了一个“隐藏的”全局变量:a=5object=Class.new{define_method(
使用散列定义的访问器方法动态创建对象的最简单方法是什么?例如,如果我有一个散列:{foo:"Foo",bar:"Bar"}我想要一个具有访问器方法foo、foo=、bar和bar=的对象,其初始值分别为"Foo"和"Bar"。我可以想到这样做:moduleObjectWithAccessordefself.newh;Struct.new(*h.keys).new(*h.values)endendo=ObjectWithAccessor.new(foo:"Foo",bar:"Bar")o.foo#=>"Foo"但是,我不需要它们的多个实例具有相同的特定键集,而是希望每次都使用可能不同的键
我在这方面尝试了很多URL,在我遇到这个特定的之前,它们似乎都很好:require'rubygems'require'nokogiri'require'open-uri'doc=Nokogiri::HTML(open("http://www.moxyst.com/fashion/men-clothing/underwear.html"))putsdoc这是结果:/Users/macbookair/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/open-uri.rb:353:in`open_http':404NotFound(OpenURI::HT
我的Ruby-on-Rails项目中有以下文件结构,用于规范:/spec/msd/serviceservice_spec.rb/support/my_modulerequests_stubs.rb我的request_stubs.rb有:moduleMyModule::RequestsStubsmodule_functiondeflist_clientsurl="dummysite.com/clients"stub_request(:get,url).to_return(status:200,body:"clientsbody")endend在我的service_spec.rb我有:re