Add latest blog component

This commit is contained in:
Carson Clarke-Magrab 2024-06-13 14:37:51 -04:00
parent 1b1b3508e3
commit 7cb6ca1ffd
10 changed files with 154 additions and 32 deletions

View File

@ -1,20 +0,0 @@
---
draft: false
title: Screen Space God Rays
tags:
- graphics
---
While thinking about graphical improvements to [[01.far-reaches|The Far Reaches]], I landed on the decision to invest some time into environmental weather effects like rain, snow, clouds, etc. I was deeply inspired by [t3ssel8r's video](https://www.youtube.com/watch?v=fSNdZ82I-eQ) on god rays (and much of his other stuff) and decided to take a crack at it myself. Before we begin let's break this down to understand what we're talking about here starting with *god rays*.
## God Rays
You've seen these before likely both in real life and in video games.
> [!caption|center]
> ![[crepuscular_rays_real.png]]
"God Rays"
The scientific term for this phenomenon is called **crepuscular rays** and the term in the graphics programming world is **volumetric light scattering**. These effects are caused by clouds or other objects and give the impression of "shafts" of light emitting from the sun. Essentially the shadows from the clouds create shadowed and un-shadowed regions of the atmosphere where light is being scattered and the contrast between these regions gives the effect of "shafts" of light emerging from the sun.
## Implementation

View File

@ -0,0 +1,27 @@
---
draft: false
title: God Rays
tags:
- graphics
created: 2024-06-12
date: 2024-06-13
aliases:
- God Rays
description: In this post we go over what are god rays and a couple different high-level approaches to them followed by my personal implementation.
---
While thinking about graphical improvements to [[01.far-reaches|The Far Reaches]], I landed on the decision to invest some time into environmental weather effects like rain, snow, clouds, etc. I was deeply inspired by [t3ssel8r's video](https://www.youtube.com/watch?v=fSNdZ82I-eQ) on god rays (and much of his other stuff) and decided to take a crack at it myself. Before we begin let's break this down to understand what we're talking about here starting with *god rays*.
## God Rays
You've seen these before likely both in real life and in video games.
> [!caption|center]
> ![[crepuscular_rays_real.png]]
"God Rays"
The scientific term for this phenomenon is called **crepuscular rays**. *Crepuscular* meaning "of or related to twilight" referring to the fact that this effect usually occurs during twilight. In the graphics world the term is **volumetric light scattering**, referring to how the light "scatters" in the atmosphere.
These effects are caused by clouds or other objects and give the impression of "shafts" of light emitting from the sun. Essentially the shadows from the clouds create shadowed and un-shadowed regions of the atmosphere where light is being scattered and the contrast between these regions gives the effect of "shafts" of light emerging from the sun.
## Implementation

View File

@ -2,9 +2,6 @@
title: Carson's Blog
---
> [!info] Latest Blog
> [[01.god-rays|Screen Space God Rays]]
A long time ago in a year known to many by 2003, I played my first "real" video game: **Pokémon Sapphire**. After encountering it in a Walmart in the great state of Maine, I quickly became enamored with the vaguely whale-shaped creature on the box art for the game. And so I began my scheming to acquire the game for myself.
In about ~0.03 seconds I had formulated my plan. It was simple. Brilliant even. All I need do was ask my grandmother who was with me at that fated Walmart for it. The trick? My parents weren't with us to say no.

View File

@ -20,6 +20,7 @@ export const defaultContentPageLayout: PageLayout = {
Component.ArticleTitle(),
Component.ContentMeta(),
Component.TagList(),
Component.RecentBlog(),
Component.Comments(),
],
left: [

View File

@ -42,11 +42,15 @@ const defaultOptions: BreadcrumbOptions = {
function formatCrumb(displayName: string, baseSlug: FullSlug, currentSlug: SimpleSlug): CrumbData {
return {
displayName: displayName.replaceAll("-", " "),
displayName: capitalize(displayName.replaceAll("-", " ")),
path: resolveRelative(baseSlug, currentSlug),
}
}
function capitalize(title: string) {
return title.charAt(0).toUpperCase() + title.slice(1);
}
export default ((opts?: Partial<BreadcrumbOptions>) => {
// Merge options with defaults
const options: BreadcrumbOptions = { ...defaultOptions, ...opts }

View File

@ -51,11 +51,15 @@ export class FileNode {
constructor(slugSegment: string, displayName?: string, file?: QuartzPluginData, depth?: number) {
this.children = []
this.name = slugSegment
this.displayName = displayName ?? file?.frontmatter?.title ?? slugSegment
this.displayName = this.capitalize(displayName ?? file?.frontmatter?.title ?? slugSegment)
this.file = file ? clone(file) : null
this.depth = depth ?? 0
}
private capitalize(title: string) {
return title.charAt(0).toUpperCase() + title.slice(1);
}
private insert(fileData: DataWrapper) {
if (fileData.path.length === 0) {
return

View File

@ -0,0 +1,64 @@
import style from "./styles/recentblog.scss"
import { i18n } from "../i18n"
import { resolveRelative } from "../util/path"
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
export default (() => {
const RecentBlog: QuartzComponent = ({
allFiles,
fileData,
cfg
}: QuartzComponentProps) => {
const page = allFiles.reduce((prev, curr) => {
console.log(fileData.filePath)
if (!curr.filePath?.startsWith("content/blogs/")) {
return prev
} else if (!prev.filePath?.startsWith("content/blogs/")) {
return curr
}
const prevDate = prev.dates?.created ?? new Date(1970, 1, 1)
const currDate = curr.dates?.created ?? new Date(1970, 1, 1)
if (currDate > prevDate) {
return curr
}
return prev
}, allFiles[0])
const title = page.frontmatter?.title ?? i18n(cfg.locale).propertyDefaults.title
const parseDate = (date: Date) => {
return date.toLocaleDateString('en-US') //`${date.getFullYear()}/${date.getMonth()}/${date.getDay()}`
}
return fileData.filePath?.startsWith("content/index") ? (
<blockquote class="callout blog" data-callout="blog">
<div class="callout-title">
<div class="callout-icon"></div>
<div class="callout-title-inner">
<p>Latest Blog </p>
</div>
</div>
<div class="preview">
<img class="preview-image" src="./Resources/crepuscular_rays_fake.png" width="150" height="150" />
<div class="preview-content">
<div class="preview-title">
<a href={resolveRelative(fileData.slug!, page.slug!)} class="internal">
{title}
</a>
<i>{parseDate(page.dates?.published!)}</i>
</div>
<p>{page.description}</p>
</div>
</div>
</blockquote>
) : <></>
}
RecentBlog.css = style
return RecentBlog
}) satisfies QuartzComponentConstructor

View File

@ -21,6 +21,7 @@ import RecentNotes from "./RecentNotes"
import Breadcrumbs from "./Breadcrumbs"
import Comments from "./Comments"
import RecentBlog from "./RecentBlog"
export {
ArticleTitle,
@ -45,5 +46,6 @@ export {
NotFound,
Breadcrumbs,
Comments
Comments,
RecentBlog
}

View File

@ -0,0 +1,34 @@
.preview {
display: flex;
flex-direction: row;
padding: 16px 16px;
border-style: solid;
border-color: #00bfa544;
border-width: 1px;
border-radius: 5px;
background: #00bfa510;
& > .preview-image {
margin: 0px 0px;
}
& > .preview-content {
margin: 0px 10px;
& > .preview-title {
display: flex;
justify-content: space-between;
margin-top: 6px;
& > a {
font-size: 20;
}
}
& > p {
margin: 0px 0px;
margin-top: 4px;
}
}
}

View File

@ -33,6 +33,15 @@ img:active:not(.Logo) {
background:var(--background-primary);
}
/*----Blog Callouts----*/
.callout[data-callout="blog"] {
--color: #00bfa5;
--border: rgba(0, 0, 0, 0);
--bg: rgba(0, 0, 0, 0);
--callout-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW5ld3NwYXBlciI+PHBhdGggZD0iTTQgMjJoMTZhMiAyIDAgMCAwIDItMlY0YTIgMiAwIDAgMC0yLTJIOGEyIDIgMCAwIDAtMiAydjE2YTIgMiAwIDAgMS0yIDJabTAgMGEyIDIgMCAwIDEtMi0ydi05YzAtMS4xLjktMiAyLTJoMiIvPjxwYXRoIGQ9Ik0xOCAxNGgtOCIvPjxwYXRoIGQ9Ik0xNSAxOGgtNSIvPjxwYXRoIGQ9Ik0xMCA2aDh2NGgtOFY2WiIvPjwvc3ZnPg==");
}
/*----Faux Grid Callouts----*/
/*---float left---*/
@ -42,10 +51,9 @@ img:active:not(.Logo) {
--bg: rgba(0, 0, 0, 0);
--callout-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW5ld3NwYXBlciI+PHBhdGggZD0iTTQgMjJoMTZhMiAyIDAgMCAwIDItMlY0YTIgMiAwIDAgMC0yLTJIOGEyIDIgMCAwIDAtMiAydjE2YTIgMiAwIDAgMS0yIDJabTAgMGEyIDIgMCAwIDEtMi0ydi05YzAtMS4xLjktMiAyLTJoMiIvPjxwYXRoIGQ9Ik0xOCAxNGgtOCIvPjxwYXRoIGQ9Ik0xNSAxOGgtNSIvPjxwYXRoIGQ9Ik0xMCA2aDh2NGgtOFY2WiIvPjwvc3ZnPg==");
float: left;
width: 45%;
margin: auto;
width: 48%;
margin: auto 1%;
clear: left;
margin-left: 20px;
}
/* mobile breakpoint */
@ -53,6 +61,7 @@ img:active:not(.Logo) {
.callout[data-callout="gridfloatleft"] {
width: 100%;
float: none;
margin: 20px auto;
}
}
@ -64,10 +73,9 @@ img:active:not(.Logo) {
--bg: rgba(0, 0, 0, 0);
--callout-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW5ld3NwYXBlciI+PHBhdGggZD0iTTQgMjJoMTZhMiAyIDAgMCAwIDItMlY0YTIgMiAwIDAgMC0yLTJIOGEyIDIgMCAwIDAtMiAydjE2YTIgMiAwIDAgMS0yIDJabTAgMGEyIDIgMCAwIDEtMi0ydi05YzAtMS4xLjktMiAyLTJoMiIvPjxwYXRoIGQ9Ik0xOCAxNGgtOCIvPjxwYXRoIGQ9Ik0xNSAxOGgtNSIvPjxwYXRoIGQ9Ik0xMCA2aDh2NGgtOFY2WiIvPjwvc3ZnPg==");
float: right;
width: 45%;
margin: auto;
width: 48%;
margin: auto 1%;
clear: right;
margin-right: 20px;
}
/* mobile breakpoint */
@ -75,6 +83,7 @@ img:active:not(.Logo) {
.callout[data-callout="gridfloatright"] {
width: 100%;
float: none;
margin: 20px auto;
}
}