canvas tutorial 中文版 Canvas - Web API 接口参考 | MDN (mozilla.org) 英文版
Game development | MDN (mozilla.org) canvas开发游戏示例
- 组合 Compositing
- video
Manipulating video using canvas
英文版中示例可以显示。video显示在canvas上。对像素处理后,改变显示内容。 - 基本的动画 - Web API 接口参考 | MDN (mozilla.org)
- 高级动画 - Web API 接口参考 | MDN (mozilla.org)
跨越保存图片,将图片画到canvas上,然后保存:Allowing cross-origin use of images and canvas - HTML: HyperText Markup Language | MDN (mozilla.org)
(16条消息) 手把手地教你怎么用canvas的rotate做出类似太阳系(包括月球的公转)的嵌套运动_TNTNT_T的博客-CSDN博客
3d迷宫移动:https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/A_basic_ray-caster
开源 Web 技术示例
Canvas c++ 实现
C:\dev\chromium104\src\third_party\blink\renderer\core\html\canvas\html_canvas_element.cc
HTMLCanvasElement::CreateLayer
HTMLCanvasElement::Paint 和 HTMLCanvasElement::PaintInternal 绘制2d,用skp或者image snapshot。需要unacclerate,不用gpu加速。
snapshot = snapshot->MakeUnaccelerated();
webgl:
if (IsWebGL() && PaintsIntoCanvasBuffer())
context_->MarkLayerComposited();
HTMLCanvasElement::Snapshot 可以对2d或者webgl快照出 image。
查看代码
scoped_refptr<StaticBitmapImage> HTMLCanvasElement::Snapshot(
SourceDrawingBuffer source_buffer) const {
if (size_.IsEmpty())
return nullptr;
scoped_refptr<StaticBitmapImage> image_bitmap;
if (OffscreenCanvasFrame()) { // Offscreen Canvas
DCHECK(OffscreenCanvasFrame()->OriginClean());
image_bitmap = OffscreenCanvasFrame()->Bitmap();
} else if (IsWebGL()) {
if (context_->CreationAttributes().premultiplied_alpha) {
context_->PaintRenderingResultsToCanvas(source_buffer);
if (ResourceProvider())
image_bitmap = ResourceProvider()->Snapshot();
} else {
sk_sp<SkData> pixel_data =
context_->PaintRenderingResultsToDataArray(source_buffer);
if (pixel_data) {
// If the accelerated canvas is too big, there is a logic in WebGL code
// path that scales down the drawing buffer to the maximum supported
// size. Hence, we need to query the adjusted size of DrawingBuffer.
gfx::Size adjusted_size = context_->DrawingBufferSize();
if (!adjusted_size.IsEmpty()) {
SkColorInfo color_info =
GetRenderingContextSkColorInfo().makeAlphaType(
kUnpremul_SkAlphaType);
if (color_info.colorType() == kN32_SkColorType)
color_info = color_info.makeColorType(kRGBA_8888_SkColorType);
else
color_info = color_info.makeColorType(kRGBA_F16_SkColorType);
image_bitmap = StaticBitmapImage::Create(
std::move(pixel_data),
SkImageInfo::Make(
SkISize::Make(adjusted_size.width(), adjusted_size.height()),
color_info));
}
}
}
} else if (context_) {
DCHECK(IsRenderingContext2D() || IsImageBitmapRenderingContext() ||
IsWebGPU());
image_bitmap = context_->GetImage();
}
if (image_bitmap)
DCHECK(image_bitmap->SupportsDisplayCompositing());
else
image_bitmap = CreateTransparentImage(size_);
return image_bitmap;
}
HTMLCanvasElement::toDataURL 生成可以在html中写的<image src"data;xx>图片资源。
HTMLCanvasElement::toBlob 都对应有 canvas的js函数吧。
决定是否cpu or gpu 绘制canvas:
// If the canvas meets the criteria to use accelerated-GPU rendering, and
// the user signals that the canvas will not be read frequently through
// getImageData, which is a slow operation with GPU, the canvas will try to
// use accelerated-GPU rendering.
// If any of the two conditions fails, or if the creation of accelerated
// resource provider fails, the canvas will fallback to CPU rendering.
UMA_HISTOGRAM_BOOLEAN(
"Blink.Canvas.2DLayerBridge.WillReadFrequently",
context_ && context_->CreationAttributes().will_read_frequently);
if (ShouldAccelerate() && context_ &&
!context_->CreationAttributes().will_read_frequently) {
canvas2d_bridge_ = Create2DLayerBridge(RasterMode::kGPU);
}
if (!canvas2d_bridge_) {
canvas2d_bridge_ = Create2DLayerBridge(RasterMode::kCPU);
}
GetSourceImageForCanvas
通知image变化:HTMLCanvasElement::NotifyListenersCanvasChanged()
阻止不支持webgl:HTMLCanvasElement::IsWebGLBlocked()
webgl代码:src\third_party\blink\renderer\modules\webgl
canvas代码:src\third_party\blink\renderer\modules\canvas 这个目录的 README.md
C:\dev\chromium104\src\third_party\blink\renderer\core\paint\html_canvas_painter.cc
RecordForeignLayer
c:\dev\chromium104\src\third_party\blink\renderer\platform\graphics\paint\foreign_layer_display_item.cc
about://gpu 可以查看目前canvas的gpu开启没有。
What to Know
- In Chrome, go to Chrome Menu > Settings > Advanced. Under System, enable Use hardware acceleration when available.这个被关掉后,其他开关都打不开gpu了。
- To force acceleration, enter chrome://flags in the search bar. Under Override software rendering list, set to Enabled, then select Relaunch. 忽略设置的cpu渲染,强制gpu。
- You can check whether hardware acceleration is turned on in Chrome by typing
chrome://gpu
into the address bar at the top of the browser.
chrome在headless模式,是不启动gpu模式的。可以通过chrome://inspect 打开监控的无头浏览器,输入 chrome://gpu查看,全是软渲染。
Issue 765284: Support GPU hardware in headless mode
- canvas 2d时:
在软渲染时,canvas的绘制指令通过cpu生成成了 layer的picture, 即skp,可以获取skp将其显示。
而在gpu绘制时,生成layer是textureLayer, 通过外部gpu绘制,这时是没有绘制指令的。无法通过skp重现。(可能是直接gpu绘制了?)
canvas webgl (canvas.getContext("webgl") 获得。有2d,3d api。
在canvas是获取的3d webgl上下文画笔时,会需要swiftshader软渲染。是必现生成texturelayer的。
而且某些情况查看layer时会崩溃(与这个网页有关。和webgl无关,直接打开webgl示例可以正常显示layers视图),比如:Simple color animation - Web APIs | MDN (mozilla.org)
Canvas 是 HTML5 提供的一个特性,你可以把它当做一个载体,简单的说就是一张白纸。而 Canvas 2D 相当于获取了内置的二维图形接口,也就是二维画笔。Canvas 3D 是获取基于 WebGL的图形接口,相当于三维画笔。你可以选择不同的画笔在上面作画。
OpenGL是 底层的驱动级的图形接口(是显卡有直接关系的) 类似于 DirectX. 但是这种底层的 OpenGL 是 寄生于浏览器的JavaScript无法涉及的。但是为了让 Web 拥有更强大的 图形处理能力 2010年时候WebGL被推出来。WebGL 允许工程师使用JS 去调用部分封装过的 OpenGL ES2.0 标准接口去 提供硬件级别的3D图形加速功能。
Skia 是一个开源的2D图形库。SwiftShader是一个高性能的,基于CPU的OpenGLES和Direct3D图形APIs的实现。它的目标是为高级3D图形提供硬件独立性。
WebGL - Web API 接口参考 | MDN (mozilla.org)
https://threejs.org/ webgl 3d 封装库
WebGL 从画布中截屏
var gl = canvas.getContext("webgl", {preserveDrawingBuffer: true});
创建canvas和测试进入加速模式:
TEST_F(HTMLCanvasPainterTest, Canvas2DLayerAppearsInLayerTree) {
// Insert a <canvas> and force it into accelerated mode.
// Not using SetBodyInnerHTML() because we need to test before document
// lifecyle update.
GetDocument().body()->setInnerHTML("<canvas width=300 height=200>");
auto* element = To<HTMLCanvasElement>(GetDocument().body()->firstChild());
CanvasContextCreationAttributesCore attributes;
attributes.alpha = true;
CanvasRenderingContext* context =
element->GetCanvasRenderingContext("2d", attributes);
gfx::Size size(300, 200);
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeCanvas2DLayerBridge(size);
element->SetResourceProviderForTesting(nullptr, std::move(bridge), size);
ASSERT_EQ(context, element->RenderingContext());
ASSERT_TRUE(context->IsComposited());
ASSERT_TRUE(element->IsAccelerated());
// Force the page to paint.
element->PreFinalizeFrame();
context->FinalizeFrame();
element->PostFinalizeFrame();
UpdateAllLifecyclePhasesForTest();
// Fetch the layer associated with the <canvas>, and check that it was
// correctly configured in the layer tree.
const cc::Layer* layer = context->CcLayer();
ASSERT_TRUE(layer);
EXPECT_TRUE(HasLayerAttached(*layer));
EXPECT_EQ(gfx::Size(300, 200), layer->bounds());
}