<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://dreamcast.wiki/wiki/index.php?action=history&amp;feed=atom&amp;title=Drawing_a_Texture</id>
	<title>Drawing a Texture - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://dreamcast.wiki/wiki/index.php?action=history&amp;feed=atom&amp;title=Drawing_a_Texture"/>
	<link rel="alternate" type="text/html" href="https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;action=history"/>
	<updated>2026-05-28T12:21:07Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3775&amp;oldid=prev</id>
		<title>Cooljerk: Blanked the page</title>
		<link rel="alternate" type="text/html" href="https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3775&amp;oldid=prev"/>
		<updated>2025-07-18T12:50:38Z</updated>

		<summary type="html">&lt;p&gt;Blanked the page&lt;/p&gt;
&lt;a href=&quot;https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;amp;diff=3775&amp;amp;oldid=3745&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Cooljerk</name></author>
	</entry>
	<entry>
		<id>https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3745&amp;oldid=prev</id>
		<title>Cooljerk at 15:03, 5 April 2025</title>
		<link rel="alternate" type="text/html" href="https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3745&amp;oldid=prev"/>
		<updated>2025-04-05T15:03:46Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 15:03, 5 April 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l88&quot;&gt;Line 88:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 88:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Let’s begin by creating our Polygon context. We want to draw the background texture to the entire screen. We can do that like so:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Let’s begin by creating our Polygon context. We want to draw the background texture to the entire screen. We can do that like so:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_poly_cxt_txr(	&amp;amp;cxt, 			/* Destination Context */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_poly_cxt_txr(	&amp;amp;cxt, 			/* Destination Context */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;				&lt;/del&gt;PVR_LIST_OP_POLY, 	/* Flags */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; 				&lt;/ins&gt;PVR_LIST_OP_POLY, 	/* Flags */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;				&lt;/del&gt;PVR_TXRFMT_RGB565, 	/* Texture Format */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; 				&lt;/ins&gt;PVR_TXRFMT_RGB565, 	/* Texture Format */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;				&lt;/del&gt;512, 				/* Texture Width */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; 				&lt;/ins&gt;512, 				/* Texture Width */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;				&lt;/del&gt;512, 				/* Texture Height */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; 				&lt;/ins&gt;512, 				/* Texture Height */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;				&lt;/del&gt;back_tex, 			/* TextureID */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; 				&lt;/ins&gt;back_tex, 			/* TextureID */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;			&lt;/del&gt;PVR_FILTER_BILINEAR);		/* Filtering */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; 			&lt;/ins&gt;PVR_FILTER_BILINEAR);		/* Filtering */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_poly_compile(&amp;amp;hdr, &amp;amp;cxt);&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_poly_compile(&amp;amp;hdr, &amp;amp;cxt);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_prim(&amp;amp;hdr, sizeof(hdr));&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_prim(&amp;amp;hdr, sizeof(hdr));&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Cooljerk</name></author>
	</entry>
	<entry>
		<id>https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3714&amp;oldid=prev</id>
		<title>Cooljerk at 14:24, 5 April 2025</title>
		<link rel="alternate" type="text/html" href="https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3714&amp;oldid=prev"/>
		<updated>2025-04-05T14:24:50Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 14:24, 5 April 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;DRAWING A TEXTURE&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The dreamcast does not draw like a modern GPU, it doesn’t have a GPU at all. It has a PVR Core which uses deferred rendering. The way this works is that a small amount of memory inside the Dreamcast VRAM is set aside to hold vertex data. Instead of rasterizing each polygon as they are sent to the dreamcast and immediately drawing it to the destination, the Dreamcast instead caches all polygons upfront. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Once &lt;/ins&gt;all the vertecies for the polygons in the scene are collected, it renders &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the output in steps, one 32x32 pixel tiles at a time&lt;/ins&gt;. This has a bunch of really cool added benefits, notably that you do not have to sort polygons for transparancies to work. Overdraw is also generally not a thing, since only the exact amount of pixels needed for the destination are drawn. Every single pixel drawn is depth tested against all polygons around it during rasterization. This means pixel perfect z-buffers!&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;First, we need to talk about how the dreamcast draws. &lt;/del&gt;The dreamcast does not draw like a modern GPU, it doesn’t have a GPU at all. It has a PVR Core which uses deferred rendering. The way this works is that a small amount of memory inside the Dreamcast VRAM is set aside to hold vertex data. Instead of rasterizing each polygon as they are sent to the dreamcast and immediately drawing it to the destination, the Dreamcast instead caches all polygons upfront &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;into these memory bins, which are known as Object Polygon Buffers, or OPBs for short&lt;/del&gt;. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;One &lt;/del&gt;all the vertecies for the polygons in the scene are collected, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;you tell the dreamcast that the scene is done and &lt;/del&gt;it renders. This has a bunch of really cool added benefits, notably that you do not have to sort polygons for transparancies to work. Overdraw is also generally not a thing, since only the exact amount of pixels needed for the destination are drawn. Every single pixel drawn is depth tested against all polygons around it during rasterization. This means pixel perfect z-buffers!&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;There are 5 types &lt;/del&gt;of &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Object Polygon Buffers in VRAM, which determine attributes about the polygon rendered. They are the Opaque Polygon Bin, the Opaque Modifier Polygon Bin, the Translucent polygon bin, the Translucent modifier polygon bin, and the punch-thru polygon bin. The type of bin a vertex belongs to determines what kind of polygon it will be. Broadly, there are 3 types: Opaque, Translucent, and Punch-Thru. We’ll talk about modifier volumes later.&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;=== Types &lt;/ins&gt;of &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Polygons ===&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Opaque Polygons are fully visible, no holes in it. If it is texture mapped, then the texture cannot have an alpha channel in it, it must be only RGB.  &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;There are 5 types of polygons that are rendered. They are the Opaque Polygons, the Opaque Modifier Polygons, the Translucent polygons, the Translucent modifier polygons, and punch-thru polygons. &lt;/ins&gt;Opaque Polygons are fully visible, no holes in it. If it is texture mapped, then the texture cannot have an alpha channel in it, it must be only RGB&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;. Translucent Polygons are what we would think of as true-color 32-bit in modern computing. It means colors are represented as ARGB, providing an alpha channel. When used on a texture mapped polygon, the individual alpha channels of pixels in the texture determine the visibility. Instead of per-polygon transparency, the dreamcast does per-pixel! Pixels can be transparent in a range depending on the bitdepth. An offshoot of Translucent Polygons are Punch-Thru polygons. Data-wise, these are basically the same as a translucent polygon, except any value in the alpha channel besides 0 is treated as 100% transparent. That means pixels are either entirely visible, or entirely transparent. It is said to “punch-through” because the transparent pixels look like holes punched through the polygon&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Translucent Polygons are what we would think &lt;/del&gt;of &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;as true-color 32-bit &lt;/del&gt;in &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;modern computing&lt;/del&gt;. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;It means colors &lt;/del&gt;are &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;represented &lt;/del&gt;as &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;ARGB, providing an alpha channel&lt;/del&gt;. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;When used on &lt;/del&gt;a &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;texture mapped &lt;/del&gt;polygon, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the individual alpha channels &lt;/del&gt;of &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;pixels in &lt;/del&gt;the &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;texture determine the visibility. Instead &lt;/del&gt;of &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;per-&lt;/del&gt;polygon &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;transparency, the dreamcast does per-pixel! Pixels can be transparent in &lt;/del&gt;a &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;range depending on the bitdepth. &lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;We need to determine how much VRAM space to reserve to hold references to these polygons. Since the output is divided into 32x32 tiles during render, every tile needs space to hold polygon references that keep track &lt;/ins&gt;of &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;which polygons reside &lt;/ins&gt;in &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;that tile&lt;/ins&gt;. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Polygon references in a tile &lt;/ins&gt;are &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;stored in a linked list known &lt;/ins&gt;as &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the Object List&lt;/ins&gt;. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Nodes in the linked list can hold &lt;/ins&gt;a &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;set number of &lt;/ins&gt;polygon &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;references&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;and can point to each other for an arbitrary number &lt;/ins&gt;of &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;polygon references to be stored. These nodes are known as Object Pointer Blocks. We can set &lt;/ins&gt;the &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;size &lt;/ins&gt;of &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;each OPB for each &lt;/ins&gt;polygon &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;type with &lt;/ins&gt;a &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;KOS structure called pvr_init_params:&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;An offshoot of Translucent Polygons are Punch-Thru polygons. Data-wise, these are basically the same as a translucent polygon, except any value in the alpha channel besides 0 is treated as 100% transparent. That means pixels are either entirely visible, or entirely transparent. It is said to “punch-through” because the transparent pixels look like holes punched through the polygon.&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;static pvr_init_params_t pvr_params = {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     /* OPB (Object &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Pointer Block&lt;/ins&gt;) &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;node&lt;/ins&gt;: */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;We need to determine how much VRAM space to give each one of these polygon bins. When we render our scene, we will send our vertices to one of these bins depending on how we want the resultant polygon to be drawn. We specify how much VRAM each bin gets in the pvr_init_params_t:&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;static pvr_init_params_t pvr_params = {&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     /* OPB (Object &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Polygon Buffer&lt;/del&gt;) &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Bin allocation table&lt;/del&gt;: */&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     {&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_32, /* Enable Opaque Poly &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Bin&lt;/del&gt;: 32 word (128 byte) length */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_32, /* Enable Opaque Poly &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;OPB&lt;/ins&gt;: 32 word (128 byte) length */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_0, /* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Enable &lt;/del&gt;Opaque Modifier Poly &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Bin: 32 word (128 byte) length &lt;/del&gt; */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_0, /* &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Disable &lt;/ins&gt;Opaque Modifier Poly &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;OPB &lt;/ins&gt; */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_32, /* Enable Translucent Poly &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Bin&lt;/del&gt;: 32 word (128 byte) length  */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_32, /* Enable Translucent Poly &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;OPB&lt;/ins&gt;: 32 word (128 byte) length  */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_0, /* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Enable &lt;/del&gt;Translucent Modifier Poly &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Bin: 32 word (128 byte) length &lt;/del&gt; */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_0, /* &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Disable &lt;/ins&gt;Translucent Modifier Poly &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;OPB &lt;/ins&gt; */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_0  /* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Enable &lt;/del&gt;Punch-thru Poly &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Bin: 32 word (128 byte) length  &lt;/del&gt;*/},&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         PVR_BINSIZE_0  /* &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Disable &lt;/ins&gt;Punch-thru Poly &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;OPB&lt;/ins&gt;*/},&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     /* Vertex buffer size 512K */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     /* Vertex buffer size 512K */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     512 * 1024,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     512 * 1024,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l29&quot;&gt;Line 29:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 25:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     /* OPB Overflow count: Preallocates this many extra OPBs (sets of tile bins), allowing the PVR to use the extra space when there&amp;#039;s too much geometry in the first OPB. */&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     /* OPB Overflow count: Preallocates this many extra OPBs (sets of tile bins), allowing the PVR to use the extra space when there&amp;#039;s too much geometry in the first OPB. */&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     0&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     0&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;};&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;};&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The available sizes for allocation for each bin are as follows:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The available sizes for allocation for each bin are as follows:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;PVR_BINSIZE_0: 0-length, which disables the list&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;PVR_BINSIZE_0: 0-length, which disables the list&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;PVR_BINSIZE_8: 8-word (32-byte) length&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;PVR_BINSIZE_8: 8-word (32-byte) length&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;PVR_BINSIZE_16: 16-word (64-byte) length&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;PVR_BINSIZE_16: 16-word (64-byte) length&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;PVR_BINSIZE_32: 32-word (128-byte) length&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;PVR_BINSIZE_32: 32-word (128-byte) length&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;In the above example, we’re allocating 128-bytes to the Opaque Polygon bin, and 128-bytes to the Translucent Polygon bin. With our VRAM memory allocated for our OPBs, it’s time to create some textures. Let’s define some pointers to vram memory in our source code as global variables:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;pvr_ptr_t tex_blue;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;The number of references that can be stored is equal to the binsize. I.e. PVR_BINSIZE_8 can store 8 polygon references in this OPB node. &lt;/ins&gt;In the above example, we’re allocating 128-bytes to the Opaque Polygon bin, and 128-bytes to the Translucent Polygon bin. With our VRAM memory allocated for our OPBs, it’s time to create some textures. Let’s define some pointers to vram memory in our source code as global variables:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;pvr_ptr_t back_tex;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;pvr_ptr_t tex_blue;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;pvr_ptr_t back_tex;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;These pointers will hold the address of our textures in vram, making them our system handles for those textures. Let’s create a function that will let us allocate some memory for these textures in vram, then fill them up:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;These pointers will hold the address of our textures in vram, making them our system handles for those textures. Let’s create a function that will let us allocate some memory for these textures in vram, then fill them up:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;void textures_init(void) {&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;void textures_init(void) {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     tex_blue = pvr_mem_malloc(128 * 128 * 2);&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     tex_blue = pvr_mem_malloc(128 * 128 * 2);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     png_to_texture(&amp;quot;/rd/blue.png&amp;quot;, tex_blue, PNG_FULL_ALPHA);&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     png_to_texture(&amp;quot;/rd/blue.png&amp;quot;, tex_blue, PNG_FULL_ALPHA);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     back_tex = pvr_mem_malloc(512 * 512 * 2);&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     back_tex = pvr_mem_malloc(512 * 512 * 2);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     png_to_texture(&amp;quot;/rd/background.png&amp;quot;, back_tex, PNG_NO_ALPHA);&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     png_to_texture(&amp;quot;/rd/background.png&amp;quot;, back_tex, PNG_NO_ALPHA);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Our function begins by calling pvr_mem_malloc(). This function takes a number which represents how many bytes to allocate. We want enough room to hold all the pixels in our textures. Our Blue Texture is 128x128 pixels big, and the Dreamcast uses 16-bit color internally, despite supporting 24-bit color. 16-bits is the same as 2-bytes, which is where the 2 comes from in the above formula. Thus we need 2-bytes for each pixel, and there are 128x128 pixels. We can add the math into the parameters so it’s more readable. Pvr_mem_malloc returns the vram address where it allocated the space, which we save in our tex_blue pvr_ptr.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Our function begins by calling pvr_mem_malloc(). This function takes a number which represents how many bytes to allocate. We want enough room to hold all the pixels in our textures. Our Blue Texture is 128x128 pixels big, and the Dreamcast uses 16-bit color internally, despite supporting 24-bit color. 16-bits is the same as 2-bytes, which is where the 2 comes from in the above formula. Thus we need 2-bytes for each pixel, and there are 128x128 pixels. We can add the math into the parameters so it’s more readable. Pvr_mem_malloc returns the vram address where it allocated the space, which we save in our tex_blue pvr_ptr.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l53&quot;&gt;Line 53:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 50:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;We use each pointer to direct our png_to_texture function where to deposite the pixels it loads. png_to_texture opens a png file and returns the raw pixel data in a dreamcast pixel format. It takes a char* string that is the filepath to the png, along with a pvr_ptr that points to an allocated area of VRAM, and a flag. The flag determines how the function treats the png, and how it orders the data. There are 3 enums that an be set as the flag:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;We use each pointer to direct our png_to_texture function where to deposite the pixels it loads. png_to_texture opens a png file and returns the raw pixel data in a dreamcast pixel format. It takes a char* string that is the filepath to the png, along with a pvr_ptr that points to an allocated area of VRAM, and a flag. The flag determines how the function treats the png, and how it orders the data. There are 3 enums that an be set as the flag:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;PNG_FULL_ALPHA: The png loaded has an alpha channel. It will be turned into ARGB4444.&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;PNG_NO_ALPHA: The png loaded has no alpha channel. It will be turned into RGB565.&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;PNG_MASK_ALPHA: The png loaded has an alpha channel, but will be a punch-thru texture. It will be turned into ARGB1555.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; PNG_FULL_ALPHA: The png loaded has an alpha channel. It will be turned into ARGB4444.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; PNG_NO_ALPHA: The png loaded has no alpha channel. It will be turned into RGB565. &lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;PNG_MASK_ALPHA: The png loaded has an alpha channel, but will be a punch-thru texture. It will be turned into ARGB1555.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;We will need to know the pixel format of the texture in a moment, so take note of which flag you have set. We used FULL_ALPHA for the blue texture, and NO_ALPHA for the background texture.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;We will need to know the pixel format of the texture in a moment, so take note of which flag you have set. We used FULL_ALPHA for the blue texture, and NO_ALPHA for the background texture.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;We need a function to call that will actually Submit vertices to the Dreamcast and command it to draw. We’ll call that function DrawFrame(), although that’s a misnomer. It’s actually just submitting frame data, and the frame is drawn later. Regardless of semantics, let’s create such a function:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;We need a function to call that will actually Submit vertices to the Dreamcast and command it to draw. We’ll call that function DrawFrame(), although that’s a misnomer. It’s actually just submitting frame data, and the frame is drawn later. Regardless of semantics, let’s create such a function:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;void DrawFrame(void)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;void DrawFrame(void)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;{&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_wait_ready();&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_wait_ready();&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_scene_begin();&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_scene_begin();&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         // Rendering code in here&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         // Rendering code in here&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_scene_finish();&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     pvr_scene_finish();&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Our DrawFrame function begins with pvr_wait_ready(). This is a function that gets the PVR ready to accept vertices. This means doing some internal house keeping, as well as generally waiting for vblank to start a new frame. That means calling pvr_wait_ready(); ends the previous frame in a loop and waits for a new one to begin. If you call this twice in a loop, then your loop will run at 30 FPS. If you call it 3 times, your loop will run at 20 FPS. And so forth.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Our DrawFrame function begins with pvr_wait_ready(). This is a function that gets the PVR ready to accept vertices. This means doing some internal house keeping, as well as generally waiting for vblank to start a new frame. That means calling pvr_wait_ready(); ends the previous frame in a loop and waits for a new one to begin. If you call this twice in a loop, then your loop will run at 30 FPS. If you call it 3 times, your loop will run at 20 FPS. And so forth.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Cooljerk</name></author>
	</entry>
	<entry>
		<id>https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3713&amp;oldid=prev</id>
		<title>Cooljerk: Created page with &quot;DRAWING A TEXTURE First, we need to talk about how the dreamcast draws. The dreamcast does not draw like a modern GPU, it doesn’t have a GPU at all. It has a PVR Core which uses deferred rendering. The way this works is that a small amount of memory inside the Dreamcast VRAM is set aside to hold vertex data. Instead of rasterizing each polygon as they are sent to the dreamcast and immediately drawing it to the destination, the Dreamcast instead caches all polygons upfr...&quot;</title>
		<link rel="alternate" type="text/html" href="https://dreamcast.wiki/wiki/index.php?title=Drawing_a_Texture&amp;diff=3713&amp;oldid=prev"/>
		<updated>2025-04-05T14:14:49Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;DRAWING A TEXTURE First, we need to talk about how the dreamcast draws. The dreamcast does not draw like a modern GPU, it doesn’t have a GPU at all. It has a PVR Core which uses deferred rendering. The way this works is that a small amount of memory inside the Dreamcast VRAM is set aside to hold vertex data. Instead of rasterizing each polygon as they are sent to the dreamcast and immediately drawing it to the destination, the Dreamcast instead caches all polygons upfr...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;DRAWING A TEXTURE&lt;br /&gt;
First, we need to talk about how the dreamcast draws. The dreamcast does not draw like a modern GPU, it doesn’t have a GPU at all. It has a PVR Core which uses deferred rendering. The way this works is that a small amount of memory inside the Dreamcast VRAM is set aside to hold vertex data. Instead of rasterizing each polygon as they are sent to the dreamcast and immediately drawing it to the destination, the Dreamcast instead caches all polygons upfront into these memory bins, which are known as Object Polygon Buffers, or OPBs for short. One all the vertecies for the polygons in the scene are collected, you tell the dreamcast that the scene is done and it renders. This has a bunch of really cool added benefits, notably that you do not have to sort polygons for transparancies to work. Overdraw is also generally not a thing, since only the exact amount of pixels needed for the destination are drawn. Every single pixel drawn is depth tested against all polygons around it during rasterization. This means pixel perfect z-buffers!&lt;br /&gt;
&lt;br /&gt;
There are 5 types of Object Polygon Buffers in VRAM, which determine attributes about the polygon rendered. They are the Opaque Polygon Bin, the Opaque Modifier Polygon Bin, the Translucent polygon bin, the Translucent modifier polygon bin, and the punch-thru polygon bin. The type of bin a vertex belongs to determines what kind of polygon it will be. Broadly, there are 3 types: Opaque, Translucent, and Punch-Thru. We’ll talk about modifier volumes later.&lt;br /&gt;
&lt;br /&gt;
Opaque Polygons are fully visible, no holes in it. If it is texture mapped, then the texture cannot have an alpha channel in it, it must be only RGB. &lt;br /&gt;
&lt;br /&gt;
Translucent Polygons are what we would think of as true-color 32-bit in modern computing. It means colors are represented as ARGB, providing an alpha channel. When used on a texture mapped polygon, the individual alpha channels of pixels in the texture determine the visibility. Instead of per-polygon transparency, the dreamcast does per-pixel! Pixels can be transparent in a range depending on the bitdepth. &lt;br /&gt;
&lt;br /&gt;
An offshoot of Translucent Polygons are Punch-Thru polygons. Data-wise, these are basically the same as a translucent polygon, except any value in the alpha channel besides 0 is treated as 100% transparent. That means pixels are either entirely visible, or entirely transparent. It is said to “punch-through” because the transparent pixels look like holes punched through the polygon.&lt;br /&gt;
&lt;br /&gt;
We need to determine how much VRAM space to give each one of these polygon bins. When we render our scene, we will send our vertices to one of these bins depending on how we want the resultant polygon to be drawn. We specify how much VRAM each bin gets in the pvr_init_params_t:&lt;br /&gt;
static pvr_init_params_t pvr_params = {&lt;br /&gt;
    /* OPB (Object Polygon Buffer) Bin allocation table: */&lt;br /&gt;
    {&lt;br /&gt;
        PVR_BINSIZE_32, /* Enable Opaque Poly Bin: 32 word (128 byte) length */&lt;br /&gt;
        PVR_BINSIZE_0, /* Enable Opaque Modifier Poly Bin: 32 word (128 byte) length  */&lt;br /&gt;
        PVR_BINSIZE_32, /* Enable Translucent Poly Bin: 32 word (128 byte) length  */&lt;br /&gt;
        PVR_BINSIZE_0, /* Enable Translucent Modifier Poly Bin: 32 word (128 byte) length  */&lt;br /&gt;
        PVR_BINSIZE_0  /* Enable Punch-thru Poly Bin: 32 word (128 byte) length  */},&lt;br /&gt;
    /* Vertex buffer size 512K */&lt;br /&gt;
    512 * 1024,&lt;br /&gt;
    /* DMA Enable: Off */&lt;br /&gt;
    0,&lt;br /&gt;
    /* FSAA Enable: Off*/&lt;br /&gt;
    0,&lt;br /&gt;
    /* Translucent Autosort Disable: Off */&lt;br /&gt;
    0,&lt;br /&gt;
    /* OPB Overflow count: Preallocates this many extra OPBs (sets of tile bins), allowing the PVR to use the extra space when there&amp;#039;s too much geometry in the first OPB. */&lt;br /&gt;
    0&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
The available sizes for allocation for each bin are as follows:&lt;br /&gt;
PVR_BINSIZE_0: 0-length, which disables the list&lt;br /&gt;
PVR_BINSIZE_8: 8-word (32-byte) length&lt;br /&gt;
PVR_BINSIZE_16: 16-word (64-byte) length&lt;br /&gt;
PVR_BINSIZE_32: 32-word (128-byte) length&lt;br /&gt;
In the above example, we’re allocating 128-bytes to the Opaque Polygon bin, and 128-bytes to the Translucent Polygon bin. With our VRAM memory allocated for our OPBs, it’s time to create some textures. Let’s define some pointers to vram memory in our source code as global variables:&lt;br /&gt;
pvr_ptr_t tex_blue;&lt;br /&gt;
pvr_ptr_t back_tex;&lt;br /&gt;
&lt;br /&gt;
These pointers will hold the address of our textures in vram, making them our system handles for those textures. Let’s create a function that will let us allocate some memory for these textures in vram, then fill them up:&lt;br /&gt;
void textures_init(void) {&lt;br /&gt;
    tex_blue = pvr_mem_malloc(128 * 128 * 2);&lt;br /&gt;
    png_to_texture(&amp;quot;/rd/blue.png&amp;quot;, tex_blue, PNG_FULL_ALPHA);&lt;br /&gt;
    back_tex = pvr_mem_malloc(512 * 512 * 2);&lt;br /&gt;
    png_to_texture(&amp;quot;/rd/background.png&amp;quot;, back_tex, PNG_NO_ALPHA);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Our function begins by calling pvr_mem_malloc(). This function takes a number which represents how many bytes to allocate. We want enough room to hold all the pixels in our textures. Our Blue Texture is 128x128 pixels big, and the Dreamcast uses 16-bit color internally, despite supporting 24-bit color. 16-bits is the same as 2-bytes, which is where the 2 comes from in the above formula. Thus we need 2-bytes for each pixel, and there are 128x128 pixels. We can add the math into the parameters so it’s more readable. Pvr_mem_malloc returns the vram address where it allocated the space, which we save in our tex_blue pvr_ptr.&lt;br /&gt;
&lt;br /&gt;
We do the same with back_tex. This time, our background.png image is 512x512 pixels big. We adjust the parameter to account, and store the pointer in the appropriate pvr_ptr.&lt;br /&gt;
&lt;br /&gt;
We use each pointer to direct our png_to_texture function where to deposite the pixels it loads. png_to_texture opens a png file and returns the raw pixel data in a dreamcast pixel format. It takes a char* string that is the filepath to the png, along with a pvr_ptr that points to an allocated area of VRAM, and a flag. The flag determines how the function treats the png, and how it orders the data. There are 3 enums that an be set as the flag:&lt;br /&gt;
PNG_FULL_ALPHA: The png loaded has an alpha channel. It will be turned into ARGB4444.&lt;br /&gt;
PNG_NO_ALPHA: The png loaded has no alpha channel. It will be turned into RGB565.&lt;br /&gt;
&lt;br /&gt;
PNG_MASK_ALPHA: The png loaded has an alpha channel, but will be a punch-thru texture. It will be turned into ARGB1555.&lt;br /&gt;
&lt;br /&gt;
We will need to know the pixel format of the texture in a moment, so take note of which flag you have set. We used FULL_ALPHA for the blue texture, and NO_ALPHA for the background texture.&lt;br /&gt;
&lt;br /&gt;
We need a function to call that will actually Submit vertices to the Dreamcast and command it to draw. We’ll call that function DrawFrame(), although that’s a misnomer. It’s actually just submitting frame data, and the frame is drawn later. Regardless of semantics, let’s create such a function:&lt;br /&gt;
void DrawFrame(void)&lt;br /&gt;
{&lt;br /&gt;
    pvr_wait_ready();&lt;br /&gt;
    pvr_scene_begin();&lt;br /&gt;
        // Rendering code in here&lt;br /&gt;
    pvr_scene_finish();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Our DrawFrame function begins with pvr_wait_ready(). This is a function that gets the PVR ready to accept vertices. This means doing some internal house keeping, as well as generally waiting for vblank to start a new frame. That means calling pvr_wait_ready(); ends the previous frame in a loop and waits for a new one to begin. If you call this twice in a loop, then your loop will run at 30 FPS. If you call it 3 times, your loop will run at 20 FPS. And so forth.&lt;br /&gt;
&lt;br /&gt;
After the PVR is ready, we have a pair of calls, pvr_scene_begin() and pvr_scene_end. Everything that goes in between these calls encapsulates a full frame of the scene being drawn. In between these calls, we can further breakdown which polygon bin we are going to be working on:&lt;br /&gt;
        pvr_list_begin(PVR_LIST_OP_POLY);&lt;br /&gt;
            // Vertex code here for Opaque polygons&lt;br /&gt;
        pvr_list_finish();&lt;br /&gt;
&lt;br /&gt;
This is a pair of calls, pvr_list_begin(int) and pvr_list_finish(). pvr_list_begin takes an enum that tells it which list to bind. When a list is bound, all pvr functions will be directed towards that one. pvr_list_finish closes the bin for the scene, once a bin is closed it cannot be reopened until the next frame. In this example, we are opening the bin for opaque polygons, meaning any vertex we submit will go to that bin.&lt;br /&gt;
&lt;br /&gt;
Inside our Opaque Polygon list functions, we can create vertices and submit them. We can also create a command to let the PVR know which texture we want to use when texture mapping the polygon. We need to first create some variables:&lt;br /&gt;
    pvr_poly_cxt_t cxt;&lt;br /&gt;
    pvr_poly_hdr_t hdr;&lt;br /&gt;
    pvr_vertex_t vert;&lt;br /&gt;
&lt;br /&gt;
First, we need to create a variable to hold our polygon context. A context is an instance of the polygon parameter data, encapsulated into an object. This context is where we set which texture to draw with for the next polygon, along with the parameters for the texture. Once we have our polygon context defined, we can compile it into a pvr polygon header. A PVR Polygon Header is an object that represents a command to the PVR to setup the next polygon. It is the same size as an vertex, and thus behaves like one. You submit the polygon header the same way you submit a vertex. In fact, you can store a bunch of vertices into an array, and insert polygon headers into the array, and submit all the polygon data at once, which we’ll get into later. For now, let’s concentrate on submitting one vertex (or header) at a time.&lt;br /&gt;
&lt;br /&gt;
Our actual vertices will be stored in a structure called pvr_vertex_t. The Dreamcast and KOS have a number of predefined vertex types, which have more or less attributes depending on rendering mode. The more features a vertex or render mode has, the more space it consumes. Vertices are either 32-bytes big, or 64-bytes big. A special case is a Sprite object, which is 4 vertices squished together into one 64-byte object, meaning you can define a sprite in one vertex instead of needing 4 vertices. The types of vertices available are:&lt;br /&gt;
pvr_vertex_t: the generic, default vertex.&lt;br /&gt;
We are going with the default type. When we submit vertices to the PVR, we will use this variable and fill out the fields inside of it as needed.&lt;br /&gt;
&lt;br /&gt;
Let’s begin by creating our Polygon context. We want to draw the background texture to the entire screen. We can do that like so:&lt;br /&gt;
    pvr_poly_cxt_txr(	&amp;amp;cxt, 			/* Destination Context */&lt;br /&gt;
				PVR_LIST_OP_POLY, 	/* Flags */&lt;br /&gt;
				PVR_TXRFMT_RGB565, 	/* Texture Format */&lt;br /&gt;
				512, 				/* Texture Width */&lt;br /&gt;
				512, 				/* Texture Height */&lt;br /&gt;
				back_tex, 			/* TextureID */&lt;br /&gt;
			PVR_FILTER_BILINEAR);		/* Filtering */&lt;br /&gt;
    pvr_poly_compile(&amp;amp;hdr, &amp;amp;cxt);&lt;br /&gt;
    pvr_prim(&amp;amp;hdr, sizeof(hdr));&lt;br /&gt;
&lt;br /&gt;
We need to create a polygon context for our background texture. We fill in the appropriate fields: this is going to the opaque polygon bin, the texture has no alpha channel so it’s RGB565, the width and height are 512x512, the pointer to the texture in memory is back_tex, and we will be using bilinear filtering. With this context object created, we compile it into our header. PVR_prim() is a function that takes a vertex or header file, and send its data over to the VRAM polygon bin. It takes a second parameter with a size to know how many bytes to send to VRAM. We send our header that tells our PVR that the next polygon renders with the back_tex using bilinear filtering as an opaque polygon.&lt;br /&gt;
&lt;br /&gt;
Now, let’s set some general parameters for our vertices:&lt;br /&gt;
    vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);&lt;br /&gt;
    vert.oargb = 0;&lt;br /&gt;
    vert.flags = PVR_CMD_VERTEX;&lt;br /&gt;
&lt;br /&gt;
Our vertex contains a field for an argb definition, to give the vertex a diffuse color. We set it to pure white, 1.0 (100%) in RGBA. Our vertex also has an offset argb value, this is for specular highlights. We’ll leave it set to 0, unused. We set a command in the flag field: PVR_CMD_VERTEX. This tells the PVR to begin taking in vertices for a polygon strip. When a command is given telling the PVR that it’s the EOL for the strip, it’ll end the polygon and move onto a new one.&lt;br /&gt;
&lt;br /&gt;
With our general parameters set, lets begin making the actual position data in the vertices and uploading them to VRAM:&lt;br /&gt;
    vert.x = 0.0f;&lt;br /&gt;
    vert.y = 0.0f;&lt;br /&gt;
    vert.z = 1.0f;&lt;br /&gt;
    vert.u = 0.0f;&lt;br /&gt;
    vert.v = 0.0f;&lt;br /&gt;
    pvr_prim(&amp;amp;vert, sizeof(vert));&lt;br /&gt;
&lt;br /&gt;
each one of these sections is a single vertex. We are manually changing the XYZ coordinates of the vertex, along with the UV coordinates, before sending it to the PVR. This vertex is at 0,0,1.&lt;br /&gt;
    vert.x = 640.0f;&lt;br /&gt;
    vert.y = 0.0f;&lt;br /&gt;
    vert.z = 1.0f;&lt;br /&gt;
    vert.u = 1.0f;&lt;br /&gt;
    vert.v = 0.0f;&lt;br /&gt;
    pvr_prim(&amp;amp;vert, sizeof(vert));&lt;br /&gt;
&lt;br /&gt;
The next vertex resides at 640,0,1. Our two vertices so far have drawn a 640-pixel straight line from the left side of the screen to the right side, at Y position 0, which is the very top.&lt;br /&gt;
    vert.x = 0.0f;&lt;br /&gt;
    vert.y = 480.0f;&lt;br /&gt;
    vert.z = 1.0f;&lt;br /&gt;
    vert.u = 0.0f;&lt;br /&gt;
    vert.v = 1.0f;&lt;br /&gt;
    pvr_prim(&amp;amp;vert, sizeof(vert));&lt;br /&gt;
&lt;br /&gt;
Our next vertex is at 0,480,1. This has shot back to the left side of the screen, then all the way down to the bottom row of pixels, Y at 480. This has formed a triangle between our previous 3 vertices. However, we have not given the command that this the end of line for the triangle strip, so we can submit another vertex.&lt;br /&gt;
    vert.x = 640.0f;&lt;br /&gt;
    vert.y = 480.0f;&lt;br /&gt;
    vert.z = 1.0f;&lt;br /&gt;
    vert.u = 1.0f;&lt;br /&gt;
    vert.v = 1.0f;&lt;br /&gt;
    vert.flags = PVR_CMD_VERTEX_EOL;&lt;br /&gt;
    pvr_prim(&amp;amp;vert, sizeof(vert));&lt;br /&gt;
&lt;br /&gt;
This final vertex is at 640,480,1. It’s at the very bottom right corner of the screen. Given the previous 3 vertices, this forms a second triangle, with the area of both filling the entire 640x480 screen. We pack a command into the flag of this final vertex, “PVR_CMD_VERTEX_EOL.” This tells the PVR that this strip of 4 vertices is a single long polygon that is finished. In the end, we wound up defining a screen-filling square and filled it with our back_tex.&lt;br /&gt;
Place this call within our Main() loop and run the program, and we should get the background texture filling our screen:&lt;br /&gt;
    while(Game.Done == 0)&lt;br /&gt;
    {&lt;br /&gt;
        //Counter++;&lt;br /&gt;
        EvHandler.PollEvent(&amp;amp;Game);&lt;br /&gt;
        HandleInput(&amp;amp;Game);&lt;br /&gt;
        DrawFrame();    }&lt;br /&gt;
&lt;br /&gt;
We have successfully loaded and displayed a texture. We will come back shortly and continue learning how to use the PVR. However, our program currently has no way of responding, every time we want to make a change we have to turn off the dreamcast and wait for it to boot back up. Let’s give ourselves the ability to communicate with our program using our gamepads.&lt;/div&gt;</summary>
		<author><name>Cooljerk</name></author>
	</entry>
</feed>